xref: /aosp_15_r20/external/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptHash.c (revision 5c591343844d1f9da7da26467c4bf7efc8a7a413)
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 //** Description
36*5c591343SA. Cody Schuffelen //
37*5c591343SA. Cody Schuffelen // This file contains implementation of cryptographic functions for hashing.
38*5c591343SA. Cody Schuffelen //
39*5c591343SA. Cody Schuffelen //** Includes, Defines, and Types
40*5c591343SA. Cody Schuffelen 
41*5c591343SA. Cody Schuffelen #define _CRYPT_HASH_C_
42*5c591343SA. Cody Schuffelen #include "Tpm.h"
43*5c591343SA. Cody Schuffelen #include "CryptHash_fp.h"
44*5c591343SA. Cody Schuffelen #include "CryptHash.h"
45*5c591343SA. Cody Schuffelen #include "OIDs.h"
46*5c591343SA. Cody Schuffelen 
47*5c591343SA. Cody Schuffelen // Instance each of the hash descriptors based on the implemented algorithms
48*5c591343SA. Cody Schuffelen FOR_EACH_HASH(HASH_DEF_TEMPLATE)
49*5c591343SA. Cody Schuffelen // Instance a 'null' def.
50*5c591343SA. Cody Schuffelen HASH_DEF NULL_Def = {{0}};
51*5c591343SA. Cody Schuffelen 
52*5c591343SA. Cody Schuffelen // Create a table of pointers to the defined hash definitions
53*5c591343SA. Cody Schuffelen #define HASH_DEF_ENTRY(HASH, Hash)     &Hash##_Def,
54*5c591343SA. Cody Schuffelen PHASH_DEF       HashDefArray[] = {
55*5c591343SA. Cody Schuffelen     // for each implemented HASH, expands to: &HASH_Def,
56*5c591343SA. Cody Schuffelen     FOR_EACH_HASH(HASH_DEF_ENTRY)
57*5c591343SA. Cody Schuffelen     &NULL_Def
58*5c591343SA. Cody Schuffelen };
59*5c591343SA. Cody Schuffelen #undef HASH_DEF_ENTRY
60*5c591343SA. Cody Schuffelen 
61*5c591343SA. Cody Schuffelen 
62*5c591343SA. Cody Schuffelen //** Obligatory Initialization Functions
63*5c591343SA. Cody Schuffelen 
64*5c591343SA. Cody Schuffelen //*** CryptHashInit()
65*5c591343SA. Cody Schuffelen // This function is called by _TPM_Init do perform the initialization operations for
66*5c591343SA. Cody Schuffelen // the library.
67*5c591343SA. Cody Schuffelen BOOL
CryptHashInit(void)68*5c591343SA. Cody Schuffelen CryptHashInit(
69*5c591343SA. Cody Schuffelen     void
70*5c591343SA. Cody Schuffelen     )
71*5c591343SA. Cody Schuffelen {
72*5c591343SA. Cody Schuffelen     LibHashInit();
73*5c591343SA. Cody Schuffelen     return TRUE;
74*5c591343SA. Cody Schuffelen }
75*5c591343SA. Cody Schuffelen 
76*5c591343SA. Cody Schuffelen //*** CryptHashStartup()
77*5c591343SA. Cody Schuffelen // This function is called by TPM2_Startup(). It checks that the size of the
78*5c591343SA. Cody Schuffelen // HashDefArray is consistent with the HASH_COUNT.
79*5c591343SA. Cody Schuffelen BOOL
CryptHashStartup(void)80*5c591343SA. Cody Schuffelen CryptHashStartup(
81*5c591343SA. Cody Schuffelen     void
82*5c591343SA. Cody Schuffelen     )
83*5c591343SA. Cody Schuffelen {
84*5c591343SA. Cody Schuffelen     int         i = sizeof(HashDefArray) / sizeof(PHASH_DEF) - 1;
85*5c591343SA. Cody Schuffelen     return (i == HASH_COUNT);
86*5c591343SA. Cody Schuffelen }
87*5c591343SA. Cody Schuffelen 
88*5c591343SA. Cody Schuffelen //** Hash Information Access Functions
89*5c591343SA. Cody Schuffelen //*** Introduction
90*5c591343SA. Cody Schuffelen // These functions provide access to the hash algorithm description information.
91*5c591343SA. Cody Schuffelen 
92*5c591343SA. Cody Schuffelen //*** CryptGetHashDef()
93*5c591343SA. Cody Schuffelen // This function accesses the hash descriptor associated with a hash a
94*5c591343SA. Cody Schuffelen // algorithm. The function returns a pointer to a 'null' descriptor if hashAlg is
95*5c591343SA. Cody Schuffelen // TPM_ALG_NULL or not a defined algorithm.
96*5c591343SA. Cody Schuffelen PHASH_DEF
CryptGetHashDef(TPM_ALG_ID hashAlg)97*5c591343SA. Cody Schuffelen CryptGetHashDef(
98*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg
99*5c591343SA. Cody Schuffelen     )
100*5c591343SA. Cody Schuffelen {
101*5c591343SA. Cody Schuffelen #define GET_DEF(HASH, Hash) case ALG_##HASH##_VALUE: return &Hash##_Def;
102*5c591343SA. Cody Schuffelen     switch(hashAlg)
103*5c591343SA. Cody Schuffelen     {
104*5c591343SA. Cody Schuffelen         FOR_EACH_HASH(GET_DEF)
105*5c591343SA. Cody Schuffelen     default:
106*5c591343SA. Cody Schuffelen         return &NULL_Def;
107*5c591343SA. Cody Schuffelen     }
108*5c591343SA. Cody Schuffelen #undef GET_DEF
109*5c591343SA. Cody Schuffelen }
110*5c591343SA. Cody Schuffelen 
111*5c591343SA. Cody Schuffelen //*** CryptHashIsValidAlg()
112*5c591343SA. Cody Schuffelen // This function tests to see if an algorithm ID is a valid hash algorithm. If
113*5c591343SA. Cody Schuffelen // flag is true, then TPM_ALG_NULL is a valid hash.
114*5c591343SA. Cody Schuffelen //  Return Type: BOOL
115*5c591343SA. Cody Schuffelen //      TRUE(1)         hashAlg is a valid, implemented hash on this TPM
116*5c591343SA. Cody Schuffelen //      FALSE(0)        hashAlg is not valid for this TPM
117*5c591343SA. Cody Schuffelen BOOL
CryptHashIsValidAlg(TPM_ALG_ID hashAlg,BOOL flag)118*5c591343SA. Cody Schuffelen CryptHashIsValidAlg(
119*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg,           // IN: the algorithm to check
120*5c591343SA. Cody Schuffelen     BOOL             flag               // IN: TRUE if TPM_ALG_NULL is to be treated
121*5c591343SA. Cody Schuffelen                                         //     as a valid hash
122*5c591343SA. Cody Schuffelen     )
123*5c591343SA. Cody Schuffelen {
124*5c591343SA. Cody Schuffelen     if(hashAlg == TPM_ALG_NULL)
125*5c591343SA. Cody Schuffelen         return flag;
126*5c591343SA. Cody Schuffelen     return CryptGetHashDef(hashAlg) != &NULL_Def;
127*5c591343SA. Cody Schuffelen }
128*5c591343SA. Cody Schuffelen 
129*5c591343SA. Cody Schuffelen //*** CryptHashGetAlgByIndex()
130*5c591343SA. Cody Schuffelen // This function is used to iterate through the hashes. TPM_ALG_NULL
131*5c591343SA. Cody Schuffelen // is returned for all indexes that are not valid hashes.
132*5c591343SA. Cody Schuffelen // If the TPM implements 3 hashes, then an 'index' value of 0 will
133*5c591343SA. Cody Schuffelen // return the first implemented hash and an 'index' of 2 will return the
134*5c591343SA. Cody Schuffelen // last. All other index values will return TPM_ALG_NULL.
135*5c591343SA. Cody Schuffelen //
136*5c591343SA. Cody Schuffelen //  Return Type: TPM_ALG_ID
137*5c591343SA. Cody Schuffelen // TPM_ALG_xxx         a hash algorithm
138*5c591343SA. Cody Schuffelen // TPM_ALG_NULL        this can be used as a stop value
139*5c591343SA. Cody Schuffelen LIB_EXPORT TPM_ALG_ID
CryptHashGetAlgByIndex(UINT32 index)140*5c591343SA. Cody Schuffelen CryptHashGetAlgByIndex(
141*5c591343SA. Cody Schuffelen     UINT32           index          // IN: the index
142*5c591343SA. Cody Schuffelen     )
143*5c591343SA. Cody Schuffelen {
144*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg;
145*5c591343SA. Cody Schuffelen     if(index >= HASH_COUNT)
146*5c591343SA. Cody Schuffelen         hashAlg = TPM_ALG_NULL;
147*5c591343SA. Cody Schuffelen     else
148*5c591343SA. Cody Schuffelen         hashAlg = HashDefArray[index]->hashAlg;
149*5c591343SA. Cody Schuffelen     return hashAlg;
150*5c591343SA. Cody Schuffelen }
151*5c591343SA. Cody Schuffelen 
152*5c591343SA. Cody Schuffelen //*** CryptHashGetDigestSize()
153*5c591343SA. Cody Schuffelen // Returns the size of the digest produced by the hash. If 'hashAlg' is not a hash
154*5c591343SA. Cody Schuffelen // algorithm, the TPM will FAIL.
155*5c591343SA. Cody Schuffelen //  Return Type: UINT16
156*5c591343SA. Cody Schuffelen //   0       TPM_ALG_NULL
157*5c591343SA. Cody Schuffelen //   > 0     the digest size
158*5c591343SA. Cody Schuffelen //
159*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptHashGetDigestSize(TPM_ALG_ID hashAlg)160*5c591343SA. Cody Schuffelen CryptHashGetDigestSize(
161*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg        // IN: hash algorithm to look up
162*5c591343SA. Cody Schuffelen     )
163*5c591343SA. Cody Schuffelen {
164*5c591343SA. Cody Schuffelen     return CryptGetHashDef(hashAlg)->digestSize;
165*5c591343SA. Cody Schuffelen }
166*5c591343SA. Cody Schuffelen 
167*5c591343SA. Cody Schuffelen //*** CryptHashGetBlockSize()
168*5c591343SA. Cody Schuffelen // Returns the size of the block used by the hash. If 'hashAlg' is not a hash
169*5c591343SA. Cody Schuffelen // algorithm, the TPM will FAIL.
170*5c591343SA. Cody Schuffelen //  Return Type: UINT16
171*5c591343SA. Cody Schuffelen //   0       TPM_ALG_NULL
172*5c591343SA. Cody Schuffelen //   > 0     the digest size
173*5c591343SA. Cody Schuffelen //
174*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptHashGetBlockSize(TPM_ALG_ID hashAlg)175*5c591343SA. Cody Schuffelen CryptHashGetBlockSize(
176*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg        // IN: hash algorithm to look up
177*5c591343SA. Cody Schuffelen     )
178*5c591343SA. Cody Schuffelen {
179*5c591343SA. Cody Schuffelen     return CryptGetHashDef(hashAlg)->blockSize;
180*5c591343SA. Cody Schuffelen }
181*5c591343SA. Cody Schuffelen 
182*5c591343SA. Cody Schuffelen //*** CryptHashGetOid()
183*5c591343SA. Cody Schuffelen // This function returns a pointer to DER=encoded OID for a hash algorithm. All OIDs
184*5c591343SA. Cody Schuffelen // are full OID values including the Tag (0x06) and length byte.
185*5c591343SA. Cody Schuffelen LIB_EXPORT const BYTE *
CryptHashGetOid(TPM_ALG_ID hashAlg)186*5c591343SA. Cody Schuffelen CryptHashGetOid(
187*5c591343SA. Cody Schuffelen     TPM_ALG_ID      hashAlg
188*5c591343SA. Cody Schuffelen )
189*5c591343SA. Cody Schuffelen {
190*5c591343SA. Cody Schuffelen     return CryptGetHashDef(hashAlg)->OID;
191*5c591343SA. Cody Schuffelen }
192*5c591343SA. Cody Schuffelen 
193*5c591343SA. Cody Schuffelen //***  CryptHashGetContextAlg()
194*5c591343SA. Cody Schuffelen // This function returns the hash algorithm associated with a hash context.
195*5c591343SA. Cody Schuffelen TPM_ALG_ID
CryptHashGetContextAlg(PHASH_STATE state)196*5c591343SA. Cody Schuffelen CryptHashGetContextAlg(
197*5c591343SA. Cody Schuffelen     PHASH_STATE      state          // IN: the context to check
198*5c591343SA. Cody Schuffelen     )
199*5c591343SA. Cody Schuffelen {
200*5c591343SA. Cody Schuffelen     return state->hashAlg;
201*5c591343SA. Cody Schuffelen }
202*5c591343SA. Cody Schuffelen 
203*5c591343SA. Cody Schuffelen //** State Import and Export
204*5c591343SA. Cody Schuffelen 
205*5c591343SA. Cody Schuffelen //*** CryptHashCopyState
206*5c591343SA. Cody Schuffelen // This function is used to clone a HASH_STATE.
207*5c591343SA. Cody Schuffelen LIB_EXPORT void
CryptHashCopyState(HASH_STATE * out,const HASH_STATE * in)208*5c591343SA. Cody Schuffelen CryptHashCopyState(
209*5c591343SA. Cody Schuffelen     HASH_STATE          *out,           // OUT: destination of the state
210*5c591343SA. Cody Schuffelen     const HASH_STATE    *in             // IN: source of the state
211*5c591343SA. Cody Schuffelen     )
212*5c591343SA. Cody Schuffelen {
213*5c591343SA. Cody Schuffelen     pAssert(out->type == in->type);
214*5c591343SA. Cody Schuffelen     out->hashAlg = in->hashAlg;
215*5c591343SA. Cody Schuffelen     out->def = in->def;
216*5c591343SA. Cody Schuffelen     if(in->hashAlg != TPM_ALG_NULL)
217*5c591343SA. Cody Schuffelen     {
218*5c591343SA. Cody Schuffelen          HASH_STATE_COPY(out, in);
219*5c591343SA. Cody Schuffelen     }
220*5c591343SA. Cody Schuffelen     if(in->type == HASH_STATE_HMAC)
221*5c591343SA. Cody Schuffelen     {
222*5c591343SA. Cody Schuffelen         const HMAC_STATE    *hIn = (HMAC_STATE *)in;
223*5c591343SA. Cody Schuffelen         HMAC_STATE          *hOut = (HMAC_STATE *)out;
224*5c591343SA. Cody Schuffelen         hOut->hmacKey = hIn->hmacKey;
225*5c591343SA. Cody Schuffelen     }
226*5c591343SA. Cody Schuffelen     return;
227*5c591343SA. Cody Schuffelen }
228*5c591343SA. Cody Schuffelen 
229*5c591343SA. Cody Schuffelen //*** CryptHashExportState()
230*5c591343SA. Cody Schuffelen // This function is used to export a hash or HMAC hash state. This function
231*5c591343SA. Cody Schuffelen // would be called when preparing to context save a sequence object.
232*5c591343SA. Cody Schuffelen void
CryptHashExportState(PCHASH_STATE internalFmt,PEXPORT_HASH_STATE externalFmt)233*5c591343SA. Cody Schuffelen CryptHashExportState(
234*5c591343SA. Cody Schuffelen     PCHASH_STATE         internalFmt,   // IN: the hash state formatted for use by
235*5c591343SA. Cody Schuffelen                                         //     library
236*5c591343SA. Cody Schuffelen     PEXPORT_HASH_STATE   externalFmt    // OUT: the exported hash state
237*5c591343SA. Cody Schuffelen     )
238*5c591343SA. Cody Schuffelen {
239*5c591343SA. Cody Schuffelen     BYTE                    *outBuf = (BYTE *)externalFmt;
240*5c591343SA. Cody Schuffelen //
241*5c591343SA. Cody Schuffelen     cAssert(sizeof(HASH_STATE) <= sizeof(EXPORT_HASH_STATE));
242*5c591343SA. Cody Schuffelen     // the following #define is used to move data from an aligned internal data
243*5c591343SA. Cody Schuffelen     // structure to a byte buffer (external format data.
244*5c591343SA. Cody Schuffelen #define CopyToOffset(value)                                                     \
245*5c591343SA. Cody Schuffelen         memcpy(&outBuf[offsetof(HASH_STATE,value)], &internalFmt->value,        \
246*5c591343SA. Cody Schuffelen                 sizeof(internalFmt->value))
247*5c591343SA. Cody Schuffelen     // Copy the hashAlg
248*5c591343SA. Cody Schuffelen     CopyToOffset(hashAlg);
249*5c591343SA. Cody Schuffelen     CopyToOffset(type);
250*5c591343SA. Cody Schuffelen #ifdef HASH_STATE_SMAC
251*5c591343SA. Cody Schuffelen     if(internalFmt->type == HASH_STATE_SMAC)
252*5c591343SA. Cody Schuffelen     {
253*5c591343SA. Cody Schuffelen         memcpy(outBuf, internalFmt, sizeof(HASH_STATE));
254*5c591343SA. Cody Schuffelen         return;
255*5c591343SA. Cody Schuffelen 
256*5c591343SA. Cody Schuffelen     }
257*5c591343SA. Cody Schuffelen #endif
258*5c591343SA. Cody Schuffelen     if(internalFmt->type == HASH_STATE_HMAC)
259*5c591343SA. Cody Schuffelen     {
260*5c591343SA. Cody Schuffelen         HMAC_STATE              *from = (HMAC_STATE *)internalFmt;
261*5c591343SA. Cody Schuffelen         memcpy(&outBuf[offsetof(HMAC_STATE, hmacKey)], &from->hmacKey,
262*5c591343SA. Cody Schuffelen                sizeof(from->hmacKey));
263*5c591343SA. Cody Schuffelen     }
264*5c591343SA. Cody Schuffelen     if(internalFmt->hashAlg != TPM_ALG_NULL)
265*5c591343SA. Cody Schuffelen          HASH_STATE_EXPORT(externalFmt, internalFmt);
266*5c591343SA. Cody Schuffelen }
267*5c591343SA. Cody Schuffelen 
268*5c591343SA. Cody Schuffelen //*** CryptHashImportState()
269*5c591343SA. Cody Schuffelen // This function is used to import the hash state. This function
270*5c591343SA. Cody Schuffelen // would be called to import a hash state when the context of a sequence object
271*5c591343SA. Cody Schuffelen // was being loaded.
272*5c591343SA. Cody Schuffelen void
CryptHashImportState(PHASH_STATE internalFmt,PCEXPORT_HASH_STATE externalFmt)273*5c591343SA. Cody Schuffelen CryptHashImportState(
274*5c591343SA. Cody Schuffelen     PHASH_STATE          internalFmt,   // OUT: the hash state formatted for use by
275*5c591343SA. Cody Schuffelen                                         //     the library
276*5c591343SA. Cody Schuffelen     PCEXPORT_HASH_STATE  externalFmt    // IN: the exported hash state
277*5c591343SA. Cody Schuffelen     )
278*5c591343SA. Cody Schuffelen {
279*5c591343SA. Cody Schuffelen     BYTE                    *inBuf = (BYTE *)externalFmt;
280*5c591343SA. Cody Schuffelen //
281*5c591343SA. Cody Schuffelen #define CopyFromOffset(value)                                                   \
282*5c591343SA. Cody Schuffelen     memcpy(&internalFmt->value, &inBuf[offsetof(HASH_STATE,value)],             \
283*5c591343SA. Cody Schuffelen            sizeof(internalFmt->value))
284*5c591343SA. Cody Schuffelen 
285*5c591343SA. Cody Schuffelen     // Copy the hashAlg of the byte-aligned input structure to the structure-aligned
286*5c591343SA. Cody Schuffelen     // internal structure.
287*5c591343SA. Cody Schuffelen     CopyFromOffset(hashAlg);
288*5c591343SA. Cody Schuffelen     CopyFromOffset(type);
289*5c591343SA. Cody Schuffelen     if(internalFmt->hashAlg != TPM_ALG_NULL)
290*5c591343SA. Cody Schuffelen     {
291*5c591343SA. Cody Schuffelen #ifdef HASH_STATE_SMAC
292*5c591343SA. Cody Schuffelen         if(internalFmt->type == HASH_STATE_SMAC)
293*5c591343SA. Cody Schuffelen         {
294*5c591343SA. Cody Schuffelen             memcpy(internalFmt, inBuf, sizeof(HASH_STATE));
295*5c591343SA. Cody Schuffelen             return;
296*5c591343SA. Cody Schuffelen         }
297*5c591343SA. Cody Schuffelen #endif
298*5c591343SA. Cody Schuffelen         internalFmt->def = CryptGetHashDef(internalFmt->hashAlg);
299*5c591343SA. Cody Schuffelen         HASH_STATE_IMPORT(internalFmt, inBuf);
300*5c591343SA. Cody Schuffelen         if(internalFmt->type == HASH_STATE_HMAC)
301*5c591343SA. Cody Schuffelen         {
302*5c591343SA. Cody Schuffelen             HMAC_STATE              *to = (HMAC_STATE *)internalFmt;
303*5c591343SA. Cody Schuffelen             memcpy(&to->hmacKey, &inBuf[offsetof(HMAC_STATE, hmacKey)],
304*5c591343SA. Cody Schuffelen                    sizeof(to->hmacKey));
305*5c591343SA. Cody Schuffelen         }
306*5c591343SA. Cody Schuffelen     }
307*5c591343SA. Cody Schuffelen }
308*5c591343SA. Cody Schuffelen 
309*5c591343SA. Cody Schuffelen //** State Modification Functions
310*5c591343SA. Cody Schuffelen 
311*5c591343SA. Cody Schuffelen //***HashEnd()
312*5c591343SA. Cody Schuffelen // Local function to complete a hash that uses the hashDef instead of an algorithm
313*5c591343SA. Cody Schuffelen // ID. This function is used to complete the hash and only return a partial digest.
314*5c591343SA. Cody Schuffelen // The return value is the size of the data copied.
315*5c591343SA. Cody Schuffelen static UINT16
HashEnd(PHASH_STATE hashState,UINT32 dOutSize,PBYTE dOut)316*5c591343SA. Cody Schuffelen HashEnd(
317*5c591343SA. Cody Schuffelen     PHASH_STATE      hashState,     // IN: the hash state
318*5c591343SA. Cody Schuffelen     UINT32           dOutSize,      // IN: the size of receive buffer
319*5c591343SA. Cody Schuffelen     PBYTE            dOut           // OUT: the receive buffer
320*5c591343SA. Cody Schuffelen     )
321*5c591343SA. Cody Schuffelen {
322*5c591343SA. Cody Schuffelen     BYTE                temp[MAX_DIGEST_SIZE];
323*5c591343SA. Cody Schuffelen     if((hashState->hashAlg == TPM_ALG_NULL)
324*5c591343SA. Cody Schuffelen        || (hashState->type != HASH_STATE_HASH))
325*5c591343SA. Cody Schuffelen         dOutSize = 0;
326*5c591343SA. Cody Schuffelen     if(dOutSize > 0)
327*5c591343SA. Cody Schuffelen     {
328*5c591343SA. Cody Schuffelen         hashState->def = CryptGetHashDef(hashState->hashAlg);
329*5c591343SA. Cody Schuffelen         // Set the final size
330*5c591343SA. Cody Schuffelen         dOutSize = MIN(dOutSize, hashState->def->digestSize);
331*5c591343SA. Cody Schuffelen         // Complete into the temp buffer and then copy
332*5c591343SA. Cody Schuffelen         HASH_END(hashState, temp);
333*5c591343SA. Cody Schuffelen         // Don't want any other functions calling the HASH_END method
334*5c591343SA. Cody Schuffelen         // directly.
335*5c591343SA. Cody Schuffelen #undef HASH_END
336*5c591343SA. Cody Schuffelen         memcpy(dOut, &temp, dOutSize);
337*5c591343SA. Cody Schuffelen     }
338*5c591343SA. Cody Schuffelen     hashState->type = HASH_STATE_EMPTY;
339*5c591343SA. Cody Schuffelen     return (UINT16)dOutSize;
340*5c591343SA. Cody Schuffelen }
341*5c591343SA. Cody Schuffelen 
342*5c591343SA. Cody Schuffelen //*** CryptHashStart()
343*5c591343SA. Cody Schuffelen // Functions starts a hash stack
344*5c591343SA. Cody Schuffelen // Start a hash stack and returns the digest size. As a side effect, the
345*5c591343SA. Cody Schuffelen // value of 'stateSize' in hashState is updated to indicate the number of bytes
346*5c591343SA. Cody Schuffelen // of state that were saved. This function calls GetHashServer() and that function
347*5c591343SA. Cody Schuffelen // will put the TPM into failure mode if the hash algorithm is not supported.
348*5c591343SA. Cody Schuffelen //
349*5c591343SA. Cody Schuffelen // This function does not use the sequence parameter. If it is necessary to import
350*5c591343SA. Cody Schuffelen // or export context, this will start the sequence in a local state
351*5c591343SA. Cody Schuffelen // and export the state to the input buffer. Will need to add a flag to the state
352*5c591343SA. Cody Schuffelen // structure to indicate that it needs to be imported before it can be used.
353*5c591343SA. Cody Schuffelen // (BLEH).
354*5c591343SA. Cody Schuffelen //  Return Type: UINT16
355*5c591343SA. Cody Schuffelen //  0           hash is TPM_ALG_NULL
356*5c591343SA. Cody Schuffelen // >0           digest size
357*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptHashStart(PHASH_STATE hashState,TPM_ALG_ID hashAlg)358*5c591343SA. Cody Schuffelen CryptHashStart(
359*5c591343SA. Cody Schuffelen     PHASH_STATE      hashState,     // OUT: the running hash state
360*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg        // IN: hash algorithm
361*5c591343SA. Cody Schuffelen     )
362*5c591343SA. Cody Schuffelen {
363*5c591343SA. Cody Schuffelen     UINT16               retVal;
364*5c591343SA. Cody Schuffelen 
365*5c591343SA. Cody Schuffelen     TEST(hashAlg);
366*5c591343SA. Cody Schuffelen 
367*5c591343SA. Cody Schuffelen     hashState->hashAlg = hashAlg;
368*5c591343SA. Cody Schuffelen     if(hashAlg == TPM_ALG_NULL)
369*5c591343SA. Cody Schuffelen     {
370*5c591343SA. Cody Schuffelen         retVal = 0;
371*5c591343SA. Cody Schuffelen     }
372*5c591343SA. Cody Schuffelen     else
373*5c591343SA. Cody Schuffelen     {
374*5c591343SA. Cody Schuffelen         hashState->def = CryptGetHashDef(hashAlg);
375*5c591343SA. Cody Schuffelen         HASH_START(hashState);
376*5c591343SA. Cody Schuffelen         retVal = hashState->def->digestSize;
377*5c591343SA. Cody Schuffelen     }
378*5c591343SA. Cody Schuffelen #undef HASH_START
379*5c591343SA. Cody Schuffelen     hashState->type = HASH_STATE_HASH;
380*5c591343SA. Cody Schuffelen     return retVal;
381*5c591343SA. Cody Schuffelen }
382*5c591343SA. Cody Schuffelen 
383*5c591343SA. Cody Schuffelen //*** CryptDigestUpdate()
384*5c591343SA. Cody Schuffelen // Add data to a hash or HMAC, SMAC stack.
385*5c591343SA. Cody Schuffelen //
386*5c591343SA. Cody Schuffelen void
CryptDigestUpdate(PHASH_STATE hashState,UINT32 dataSize,const BYTE * data)387*5c591343SA. Cody Schuffelen CryptDigestUpdate(
388*5c591343SA. Cody Schuffelen     PHASH_STATE      hashState,     // IN: the hash context information
389*5c591343SA. Cody Schuffelen     UINT32           dataSize,      // IN: the size of data to be added
390*5c591343SA. Cody Schuffelen     const BYTE      *data           // IN: data to be hashed
391*5c591343SA. Cody Schuffelen     )
392*5c591343SA. Cody Schuffelen {
393*5c591343SA. Cody Schuffelen     if(hashState->hashAlg != TPM_ALG_NULL)
394*5c591343SA. Cody Schuffelen     {
395*5c591343SA. Cody Schuffelen         if((hashState->type == HASH_STATE_HASH)
396*5c591343SA. Cody Schuffelen            || (hashState->type == HASH_STATE_HMAC))
397*5c591343SA. Cody Schuffelen             HASH_DATA(hashState, dataSize, (BYTE *)data);
398*5c591343SA. Cody Schuffelen #if SMAC_IMPLEMENTED
399*5c591343SA. Cody Schuffelen         else if(hashState->type == HASH_STATE_SMAC)
400*5c591343SA. Cody Schuffelen             (hashState->state.smac.smacMethods.data)(&hashState->state.smac.state,
401*5c591343SA. Cody Schuffelen                                                      dataSize, data);
402*5c591343SA. Cody Schuffelen #endif // SMAC_IMPLEMENTED
403*5c591343SA. Cody Schuffelen         else
404*5c591343SA. Cody Schuffelen             FAIL(FATAL_ERROR_INTERNAL);
405*5c591343SA. Cody Schuffelen     }
406*5c591343SA. Cody Schuffelen     return;
407*5c591343SA. Cody Schuffelen }
408*5c591343SA. Cody Schuffelen 
409*5c591343SA. Cody Schuffelen //*** CryptHashEnd()
410*5c591343SA. Cody Schuffelen // Complete a hash or HMAC computation. This function will place the smaller of
411*5c591343SA. Cody Schuffelen // 'digestSize' or the size of the digest in 'dOut'. The number of bytes in the
412*5c591343SA. Cody Schuffelen // placed in the buffer is returned. If there is a failure, the returned value
413*5c591343SA. Cody Schuffelen // is <= 0.
414*5c591343SA. Cody Schuffelen //  Return Type: UINT16
415*5c591343SA. Cody Schuffelen //       0      no data returned
416*5c591343SA. Cody Schuffelen //      > 0     the number of bytes in the digest or dOutSize, whichever is smaller
417*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptHashEnd(PHASH_STATE hashState,UINT32 dOutSize,BYTE * dOut)418*5c591343SA. Cody Schuffelen CryptHashEnd(
419*5c591343SA. Cody Schuffelen     PHASH_STATE      hashState,     // IN: the state of hash stack
420*5c591343SA. Cody Schuffelen     UINT32           dOutSize,      // IN: size of digest buffer
421*5c591343SA. Cody Schuffelen     BYTE            *dOut           // OUT: hash digest
422*5c591343SA. Cody Schuffelen     )
423*5c591343SA. Cody Schuffelen {
424*5c591343SA. Cody Schuffelen     pAssert(hashState->type == HASH_STATE_HASH);
425*5c591343SA. Cody Schuffelen     return HashEnd(hashState, dOutSize, dOut);
426*5c591343SA. Cody Schuffelen }
427*5c591343SA. Cody Schuffelen 
428*5c591343SA. Cody Schuffelen //*** CryptHashBlock()
429*5c591343SA. Cody Schuffelen // Start a hash, hash a single block, update 'digest' and return the size of
430*5c591343SA. Cody Schuffelen // the results.
431*5c591343SA. Cody Schuffelen //
432*5c591343SA. Cody Schuffelen // The 'digestSize' parameter can be smaller than the digest. If so, only the more
433*5c591343SA. Cody Schuffelen // significant bytes are returned.
434*5c591343SA. Cody Schuffelen //  Return Type: UINT16
435*5c591343SA. Cody Schuffelen //  >= 0        number of bytes placed in 'dOut'
436*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptHashBlock(TPM_ALG_ID hashAlg,UINT32 dataSize,const BYTE * data,UINT32 dOutSize,BYTE * dOut)437*5c591343SA. Cody Schuffelen CryptHashBlock(
438*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg,       // IN: The hash algorithm
439*5c591343SA. Cody Schuffelen     UINT32           dataSize,      // IN: size of buffer to hash
440*5c591343SA. Cody Schuffelen     const BYTE      *data,          // IN: the buffer to hash
441*5c591343SA. Cody Schuffelen     UINT32           dOutSize,      // IN: size of the digest buffer
442*5c591343SA. Cody Schuffelen     BYTE            *dOut           // OUT: digest buffer
443*5c591343SA. Cody Schuffelen     )
444*5c591343SA. Cody Schuffelen {
445*5c591343SA. Cody Schuffelen     HASH_STATE          state;
446*5c591343SA. Cody Schuffelen     CryptHashStart(&state, hashAlg);
447*5c591343SA. Cody Schuffelen     CryptDigestUpdate(&state, dataSize, data);
448*5c591343SA. Cody Schuffelen     return HashEnd(&state, dOutSize, dOut);
449*5c591343SA. Cody Schuffelen }
450*5c591343SA. Cody Schuffelen 
451*5c591343SA. Cody Schuffelen //*** CryptDigestUpdate2B()
452*5c591343SA. Cody Schuffelen // This function updates a digest (hash or HMAC) with a TPM2B.
453*5c591343SA. Cody Schuffelen //
454*5c591343SA. Cody Schuffelen // This function can be used for both HMAC and hash functions so the
455*5c591343SA. Cody Schuffelen // 'digestState' is void so that either state type can be passed.
456*5c591343SA. Cody Schuffelen LIB_EXPORT void
CryptDigestUpdate2B(PHASH_STATE state,const TPM2B * bIn)457*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(
458*5c591343SA. Cody Schuffelen     PHASH_STATE      state,         // IN: the digest state
459*5c591343SA. Cody Schuffelen     const TPM2B     *bIn            // IN: 2B containing the data
460*5c591343SA. Cody Schuffelen     )
461*5c591343SA. Cody Schuffelen {
462*5c591343SA. Cody Schuffelen     // Only compute the digest if a pointer to the 2B is provided.
463*5c591343SA. Cody Schuffelen     // In CryptDigestUpdate(), if size is zero or buffer is NULL, then no change
464*5c591343SA. Cody Schuffelen     // to the digest occurs. This function should not provide a buffer if bIn is
465*5c591343SA. Cody Schuffelen     // not provided.
466*5c591343SA. Cody Schuffelen     pAssert(bIn != NULL);
467*5c591343SA. Cody Schuffelen     CryptDigestUpdate(state, bIn->size, bIn->buffer);
468*5c591343SA. Cody Schuffelen     return;
469*5c591343SA. Cody Schuffelen }
470*5c591343SA. Cody Schuffelen 
471*5c591343SA. Cody Schuffelen //*** CryptHashEnd2B()
472*5c591343SA. Cody Schuffelen // This function is the same as CryptCompleteHash() but the digest is
473*5c591343SA. Cody Schuffelen // placed in a TPM2B. This is the most common use and this is provided
474*5c591343SA. Cody Schuffelen // for specification clarity. 'digest.size' should be set to indicate the number of
475*5c591343SA. Cody Schuffelen // bytes to place in the buffer
476*5c591343SA. Cody Schuffelen //  Return Type: UINT16
477*5c591343SA. Cody Schuffelen //      >=0     the number of bytes placed in 'digest.buffer'
478*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptHashEnd2B(PHASH_STATE state,P2B digest)479*5c591343SA. Cody Schuffelen CryptHashEnd2B(
480*5c591343SA. Cody Schuffelen     PHASH_STATE      state,         // IN: the hash state
481*5c591343SA. Cody Schuffelen     P2B              digest         // IN: the size of the buffer Out: requested
482*5c591343SA. Cody Schuffelen                                     //     number of bytes
483*5c591343SA. Cody Schuffelen     )
484*5c591343SA. Cody Schuffelen {
485*5c591343SA. Cody Schuffelen     return CryptHashEnd(state, digest->size, digest->buffer);
486*5c591343SA. Cody Schuffelen }
487*5c591343SA. Cody Schuffelen 
488*5c591343SA. Cody Schuffelen //*** CryptDigestUpdateInt()
489*5c591343SA. Cody Schuffelen // This function is used to include an integer value to a hash stack. The function
490*5c591343SA. Cody Schuffelen // marshals the integer into its canonical form before calling CryptDigestUpdate().
491*5c591343SA. Cody Schuffelen LIB_EXPORT void
CryptDigestUpdateInt(void * state,UINT32 intSize,UINT64 intValue)492*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(
493*5c591343SA. Cody Schuffelen     void            *state,         // IN: the state of hash stack
494*5c591343SA. Cody Schuffelen     UINT32           intSize,       // IN: the size of 'intValue' in bytes
495*5c591343SA. Cody Schuffelen     UINT64           intValue       // IN: integer value to be hashed
496*5c591343SA. Cody Schuffelen     )
497*5c591343SA. Cody Schuffelen {
498*5c591343SA. Cody Schuffelen #if LITTLE_ENDIAN_TPM
499*5c591343SA. Cody Schuffelen     intValue = REVERSE_ENDIAN_64(intValue);
500*5c591343SA. Cody Schuffelen #endif
501*5c591343SA. Cody Schuffelen     CryptDigestUpdate(state, intSize, &((BYTE *)&intValue)[8 - intSize]);
502*5c591343SA. Cody Schuffelen }
503*5c591343SA. Cody Schuffelen 
504*5c591343SA. Cody Schuffelen //** HMAC Functions
505*5c591343SA. Cody Schuffelen 
506*5c591343SA. Cody Schuffelen //*** CryptHmacStart()
507*5c591343SA. Cody Schuffelen // This function is used to start an HMAC using a temp
508*5c591343SA. Cody Schuffelen // hash context. The function does the initialization
509*5c591343SA. Cody Schuffelen // of the hash with the HMAC key XOR iPad and updates the
510*5c591343SA. Cody Schuffelen // HMAC key XOR oPad.
511*5c591343SA. Cody Schuffelen //
512*5c591343SA. Cody Schuffelen // The function returns the number of bytes in a digest produced by 'hashAlg'.
513*5c591343SA. Cody Schuffelen //  Return Type: UINT16
514*5c591343SA. Cody Schuffelen //  >= 0        number of bytes in digest produced by 'hashAlg' (may be zero)
515*5c591343SA. Cody Schuffelen //
516*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptHmacStart(PHMAC_STATE state,TPM_ALG_ID hashAlg,UINT16 keySize,const BYTE * key)517*5c591343SA. Cody Schuffelen CryptHmacStart(
518*5c591343SA. Cody Schuffelen     PHMAC_STATE      state,         // IN/OUT: the state buffer
519*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg,       // IN: the algorithm to use
520*5c591343SA. Cody Schuffelen     UINT16           keySize,       // IN: the size of the HMAC key
521*5c591343SA. Cody Schuffelen     const BYTE      *key            // IN: the HMAC key
522*5c591343SA. Cody Schuffelen     )
523*5c591343SA. Cody Schuffelen {
524*5c591343SA. Cody Schuffelen     PHASH_DEF                hashDef;
525*5c591343SA. Cody Schuffelen     BYTE *                   pb;
526*5c591343SA. Cody Schuffelen     UINT32                   i;
527*5c591343SA. Cody Schuffelen //
528*5c591343SA. Cody Schuffelen     hashDef = CryptGetHashDef(hashAlg);
529*5c591343SA. Cody Schuffelen     if(hashDef->digestSize != 0)
530*5c591343SA. Cody Schuffelen     {
531*5c591343SA. Cody Schuffelen     // If the HMAC key is larger than the hash block size, it has to be reduced
532*5c591343SA. Cody Schuffelen     // to fit. The reduction is a digest of the hashKey.
533*5c591343SA. Cody Schuffelen         if(keySize > hashDef->blockSize)
534*5c591343SA. Cody Schuffelen         {
535*5c591343SA. Cody Schuffelen             // if the key is too big, reduce it to a digest of itself
536*5c591343SA. Cody Schuffelen             state->hmacKey.t.size = CryptHashBlock(hashAlg, keySize, key,
537*5c591343SA. Cody Schuffelen                                                    hashDef->digestSize,
538*5c591343SA. Cody Schuffelen                                                    state->hmacKey.t.buffer);
539*5c591343SA. Cody Schuffelen         }
540*5c591343SA. Cody Schuffelen         else
541*5c591343SA. Cody Schuffelen         {
542*5c591343SA. Cody Schuffelen             memcpy(state->hmacKey.t.buffer, key, keySize);
543*5c591343SA. Cody Schuffelen             state->hmacKey.t.size = keySize;
544*5c591343SA. Cody Schuffelen         }
545*5c591343SA. Cody Schuffelen         // XOR the key with iPad (0x36)
546*5c591343SA. Cody Schuffelen         pb = state->hmacKey.t.buffer;
547*5c591343SA. Cody Schuffelen         for(i = state->hmacKey.t.size; i > 0; i--)
548*5c591343SA. Cody Schuffelen             *pb++ ^= 0x36;
549*5c591343SA. Cody Schuffelen 
550*5c591343SA. Cody Schuffelen         // if the keySize is smaller than a block, fill the rest with 0x36
551*5c591343SA. Cody Schuffelen         for(i = hashDef->blockSize - state->hmacKey.t.size; i > 0; i--)
552*5c591343SA. Cody Schuffelen             *pb++ = 0x36;
553*5c591343SA. Cody Schuffelen 
554*5c591343SA. Cody Schuffelen         // Increase the oPadSize to a full block
555*5c591343SA. Cody Schuffelen         state->hmacKey.t.size = hashDef->blockSize;
556*5c591343SA. Cody Schuffelen 
557*5c591343SA. Cody Schuffelen         // Start a new hash with the HMAC key
558*5c591343SA. Cody Schuffelen         // This will go in the caller's state structure and may be a sequence or not
559*5c591343SA. Cody Schuffelen         CryptHashStart((PHASH_STATE)state, hashAlg);
560*5c591343SA. Cody Schuffelen         CryptDigestUpdate((PHASH_STATE)state, state->hmacKey.t.size,
561*5c591343SA. Cody Schuffelen                           state->hmacKey.t.buffer);
562*5c591343SA. Cody Schuffelen         // XOR the key block with 0x5c ^ 0x36
563*5c591343SA. Cody Schuffelen         for(pb = state->hmacKey.t.buffer, i = hashDef->blockSize; i > 0; i--)
564*5c591343SA. Cody Schuffelen             *pb++ ^= (0x5c ^ 0x36);
565*5c591343SA. Cody Schuffelen     }
566*5c591343SA. Cody Schuffelen     // Set the hash algorithm
567*5c591343SA. Cody Schuffelen     state->hashState.hashAlg = hashAlg;
568*5c591343SA. Cody Schuffelen     // Set the hash state type
569*5c591343SA. Cody Schuffelen     state->hashState.type = HASH_STATE_HMAC;
570*5c591343SA. Cody Schuffelen 
571*5c591343SA. Cody Schuffelen     return hashDef->digestSize;
572*5c591343SA. Cody Schuffelen }
573*5c591343SA. Cody Schuffelen 
574*5c591343SA. Cody Schuffelen //*** CryptHmacEnd()
575*5c591343SA. Cody Schuffelen // This function is called to complete an HMAC. It will finish the current
576*5c591343SA. Cody Schuffelen // digest, and start a new digest. It will then add the oPadKey and the
577*5c591343SA. Cody Schuffelen // completed digest and return the results in dOut. It will not return more
578*5c591343SA. Cody Schuffelen // than dOutSize bytes.
579*5c591343SA. Cody Schuffelen //  Return Type: UINT16
580*5c591343SA. Cody Schuffelen //  >= 0        number of bytes in 'dOut' (may be zero)
581*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptHmacEnd(PHMAC_STATE state,UINT32 dOutSize,BYTE * dOut)582*5c591343SA. Cody Schuffelen CryptHmacEnd(
583*5c591343SA. Cody Schuffelen     PHMAC_STATE      state,         // IN: the hash state buffer
584*5c591343SA. Cody Schuffelen     UINT32           dOutSize,      // IN: size of digest buffer
585*5c591343SA. Cody Schuffelen     BYTE            *dOut           // OUT: hash digest
586*5c591343SA. Cody Schuffelen     )
587*5c591343SA. Cody Schuffelen {
588*5c591343SA. Cody Schuffelen     BYTE                 temp[MAX_DIGEST_SIZE];
589*5c591343SA. Cody Schuffelen     PHASH_STATE          hState = (PHASH_STATE)&state->hashState;
590*5c591343SA. Cody Schuffelen 
591*5c591343SA. Cody Schuffelen #if SMAC_IMPLEMENTED
592*5c591343SA. Cody Schuffelen     if(hState->type == HASH_STATE_SMAC)
593*5c591343SA. Cody Schuffelen         return (state->hashState.state.smac.smacMethods.end)
594*5c591343SA. Cody Schuffelen                     (&state->hashState.state.smac.state,
595*5c591343SA. Cody Schuffelen                      dOutSize,
596*5c591343SA. Cody Schuffelen                      dOut);
597*5c591343SA. Cody Schuffelen #endif
598*5c591343SA. Cody Schuffelen     pAssert(hState->type == HASH_STATE_HMAC);
599*5c591343SA. Cody Schuffelen     hState->def = CryptGetHashDef(hState->hashAlg);
600*5c591343SA. Cody Schuffelen     // Change the state type for completion processing
601*5c591343SA. Cody Schuffelen     hState->type = HASH_STATE_HASH;
602*5c591343SA. Cody Schuffelen     if(hState->hashAlg == TPM_ALG_NULL)
603*5c591343SA. Cody Schuffelen         dOutSize = 0;
604*5c591343SA. Cody Schuffelen     else
605*5c591343SA. Cody Schuffelen     {
606*5c591343SA. Cody Schuffelen     // Complete the current hash
607*5c591343SA. Cody Schuffelen         HashEnd(hState, hState->def->digestSize, temp);
608*5c591343SA. Cody Schuffelen         // Do another hash starting with the oPad
609*5c591343SA. Cody Schuffelen         CryptHashStart(hState, hState->hashAlg);
610*5c591343SA. Cody Schuffelen         CryptDigestUpdate(hState, state->hmacKey.t.size, state->hmacKey.t.buffer);
611*5c591343SA. Cody Schuffelen         CryptDigestUpdate(hState, hState->def->digestSize, temp);
612*5c591343SA. Cody Schuffelen     }
613*5c591343SA. Cody Schuffelen     return HashEnd(hState, dOutSize, dOut);
614*5c591343SA. Cody Schuffelen }
615*5c591343SA. Cody Schuffelen 
616*5c591343SA. Cody Schuffelen //*** CryptHmacStart2B()
617*5c591343SA. Cody Schuffelen // This function starts an HMAC and returns the size of the digest
618*5c591343SA. Cody Schuffelen // that will be produced.
619*5c591343SA. Cody Schuffelen //
620*5c591343SA. Cody Schuffelen // This function is provided to support the most common use of starting an HMAC
621*5c591343SA. Cody Schuffelen // with a TPM2B key.
622*5c591343SA. Cody Schuffelen //
623*5c591343SA. Cody Schuffelen // The caller must provide a block of memory in which the hash sequence state
624*5c591343SA. Cody Schuffelen // is kept.  The caller should not alter the contents of this buffer until the
625*5c591343SA. Cody Schuffelen // hash sequence is completed or abandoned.
626*5c591343SA. Cody Schuffelen //
627*5c591343SA. Cody Schuffelen //  Return Type: UINT16
628*5c591343SA. Cody Schuffelen //      > 0     the digest size of the algorithm
629*5c591343SA. Cody Schuffelen //      = 0     the hashAlg was TPM_ALG_NULL
630*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptHmacStart2B(PHMAC_STATE hmacState,TPMI_ALG_HASH hashAlg,P2B key)631*5c591343SA. Cody Schuffelen CryptHmacStart2B(
632*5c591343SA. Cody Schuffelen     PHMAC_STATE      hmacState,     // OUT: the state of HMAC stack. It will be used
633*5c591343SA. Cody Schuffelen                                     //     in HMAC update and completion
634*5c591343SA. Cody Schuffelen     TPMI_ALG_HASH    hashAlg,       // IN: hash algorithm
635*5c591343SA. Cody Schuffelen     P2B              key            // IN: HMAC key
636*5c591343SA. Cody Schuffelen     )
637*5c591343SA. Cody Schuffelen {
638*5c591343SA. Cody Schuffelen     return CryptHmacStart(hmacState, hashAlg, key->size, key->buffer);
639*5c591343SA. Cody Schuffelen }
640*5c591343SA. Cody Schuffelen 
641*5c591343SA. Cody Schuffelen //*** CryptHmacEnd2B()
642*5c591343SA. Cody Schuffelen //   This function is the same as CryptHmacEnd() but the HMAC result
643*5c591343SA. Cody Schuffelen //   is returned in a TPM2B which is the most common use.
644*5c591343SA. Cody Schuffelen //  Return Type: UINT16
645*5c591343SA. Cody Schuffelen //      >=0     the number of bytes placed in 'digest'
646*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptHmacEnd2B(PHMAC_STATE hmacState,P2B digest)647*5c591343SA. Cody Schuffelen CryptHmacEnd2B(
648*5c591343SA. Cody Schuffelen     PHMAC_STATE      hmacState,     // IN: the state of HMAC stack
649*5c591343SA. Cody Schuffelen     P2B              digest         // OUT: HMAC
650*5c591343SA. Cody Schuffelen     )
651*5c591343SA. Cody Schuffelen {
652*5c591343SA. Cody Schuffelen     return CryptHmacEnd(hmacState, digest->size, digest->buffer);
653*5c591343SA. Cody Schuffelen }
654*5c591343SA. Cody Schuffelen 
655*5c591343SA. Cody Schuffelen //** Mask and Key Generation Functions
656*5c591343SA. Cody Schuffelen //*** CryptMGF_KDF()
657*5c591343SA. Cody Schuffelen // This function performs MGF1/KDF1 or KDF2 using the selected hash. KDF1 and KDF2 are
658*5c591343SA. Cody Schuffelen // T('n') = T('n'-1) || H('seed' || 'counter') with the difference being that, with
659*5c591343SA. Cody Schuffelen // KDF1, 'counter' starts at 0 but with KDF2, 'counter' starts at 1. The caller
660*5c591343SA. Cody Schuffelen // determines which version by setting the initial value of counter to either 0 or 1.
661*5c591343SA. Cody Schuffelen // Note: Any value that is not 0 is considered to be 1.
662*5c591343SA. Cody Schuffelen //
663*5c591343SA. Cody Schuffelen // This function returns the length of the mask produced which
664*5c591343SA. Cody Schuffelen // could be zero if the digest algorithm is not supported
665*5c591343SA. Cody Schuffelen //  Return Type: UINT16
666*5c591343SA. Cody Schuffelen //      0       hash algorithm was TPM_ALG_NULL
667*5c591343SA. Cody Schuffelen //    > 0       should be the same as 'mSize'
668*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptMGF_KDF(UINT32 mSize,BYTE * mask,TPM_ALG_ID hashAlg,UINT32 seedSize,BYTE * seed,UINT32 counter)669*5c591343SA. Cody Schuffelen CryptMGF_KDF(
670*5c591343SA. Cody Schuffelen     UINT32           mSize,         // IN: length of the mask to be produced
671*5c591343SA. Cody Schuffelen     BYTE            *mask,          // OUT: buffer to receive the mask
672*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg,       // IN: hash to use
673*5c591343SA. Cody Schuffelen     UINT32           seedSize,      // IN: size of the seed
674*5c591343SA. Cody Schuffelen     BYTE            *seed,          // IN: seed size
675*5c591343SA. Cody Schuffelen     UINT32           counter        // IN: counter initial value
676*5c591343SA. Cody Schuffelen     )
677*5c591343SA. Cody Schuffelen {
678*5c591343SA. Cody Schuffelen     HASH_STATE           hashState;
679*5c591343SA. Cody Schuffelen     PHASH_DEF            hDef = CryptGetHashDef(hashAlg);
680*5c591343SA. Cody Schuffelen     UINT32               hLen;
681*5c591343SA. Cody Schuffelen     UINT32               bytes;
682*5c591343SA. Cody Schuffelen //
683*5c591343SA. Cody Schuffelen     // If there is no digest to compute return
684*5c591343SA. Cody Schuffelen     if((hDef->digestSize == 0) || (mSize == 0))
685*5c591343SA. Cody Schuffelen         return 0;
686*5c591343SA. Cody Schuffelen     if(counter != 0)
687*5c591343SA. Cody Schuffelen         counter = 1;
688*5c591343SA. Cody Schuffelen     hLen = hDef->digestSize;
689*5c591343SA. Cody Schuffelen     for(bytes = 0; bytes < mSize; bytes += hLen)
690*5c591343SA. Cody Schuffelen     {
691*5c591343SA. Cody Schuffelen         // Start the hash and include the seed and counter
692*5c591343SA. Cody Schuffelen         CryptHashStart(&hashState, hashAlg);
693*5c591343SA. Cody Schuffelen         CryptDigestUpdate(&hashState, seedSize, seed);
694*5c591343SA. Cody Schuffelen         CryptDigestUpdateInt(&hashState, 4, counter);
695*5c591343SA. Cody Schuffelen         // Get as much as will fit.
696*5c591343SA. Cody Schuffelen         CryptHashEnd(&hashState, MIN((mSize - bytes), hLen),
697*5c591343SA. Cody Schuffelen                      &mask[bytes]);
698*5c591343SA. Cody Schuffelen         counter++;
699*5c591343SA. Cody Schuffelen     }
700*5c591343SA. Cody Schuffelen     return (UINT16)mSize;
701*5c591343SA. Cody Schuffelen }
702*5c591343SA. Cody Schuffelen 
703*5c591343SA. Cody Schuffelen //*** CryptKDFa()
704*5c591343SA. Cody Schuffelen // This function performs the key generation according to Part 1 of the
705*5c591343SA. Cody Schuffelen // TPM specification.
706*5c591343SA. Cody Schuffelen //
707*5c591343SA. Cody Schuffelen // This function returns the number of bytes generated which may be zero.
708*5c591343SA. Cody Schuffelen //
709*5c591343SA. Cody Schuffelen // The 'key' and 'keyStream' pointers are not allowed to be NULL. The other
710*5c591343SA. Cody Schuffelen // pointer values may be NULL. The value of 'sizeInBits' must be no larger
711*5c591343SA. Cody Schuffelen // than (2^18)-1 = 256K bits (32385 bytes).
712*5c591343SA. Cody Schuffelen //
713*5c591343SA. Cody Schuffelen // The 'once' parameter is set to allow incremental generation of a large
714*5c591343SA. Cody Schuffelen // value. If this flag is TRUE, 'sizeInBits' will be used in the HMAC computation
715*5c591343SA. Cody Schuffelen // but only one iteration of the KDF is performed. This would be used for
716*5c591343SA. Cody Schuffelen // XOR obfuscation so that the mask value can be generated in digest-sized
717*5c591343SA. Cody Schuffelen // chunks rather than having to be generated all at once in an arbitrarily
718*5c591343SA. Cody Schuffelen // large buffer and then XORed into the result. If 'once' is TRUE, then
719*5c591343SA. Cody Schuffelen // 'sizeInBits' must be a multiple of 8.
720*5c591343SA. Cody Schuffelen //
721*5c591343SA. Cody Schuffelen // Any error in the processing of this command is considered fatal.
722*5c591343SA. Cody Schuffelen //  Return Type: UINT16
723*5c591343SA. Cody Schuffelen //     0            hash algorithm is not supported or is TPM_ALG_NULL
724*5c591343SA. Cody Schuffelen //    > 0           the number of bytes in the 'keyStream' buffer
725*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptKDFa(TPM_ALG_ID hashAlg,const TPM2B * key,const TPM2B * label,const TPM2B * contextU,const TPM2B * contextV,UINT32 sizeInBits,BYTE * keyStream,UINT32 * counterInOut,UINT16 blocks)726*5c591343SA. Cody Schuffelen CryptKDFa(
727*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg,       // IN: hash algorithm used in HMAC
728*5c591343SA. Cody Schuffelen     const TPM2B     *key,           // IN: HMAC key
729*5c591343SA. Cody Schuffelen     const TPM2B     *label,         // IN: a label for the KDF
730*5c591343SA. Cody Schuffelen     const TPM2B     *contextU,      // IN: context U
731*5c591343SA. Cody Schuffelen     const TPM2B     *contextV,      // IN: context V
732*5c591343SA. Cody Schuffelen     UINT32           sizeInBits,    // IN: size of generated key in bits
733*5c591343SA. Cody Schuffelen     BYTE            *keyStream,     // OUT: key buffer
734*5c591343SA. Cody Schuffelen     UINT32          *counterInOut,  // IN/OUT: caller may provide the iteration
735*5c591343SA. Cody Schuffelen                                     //     counter for incremental operations to
736*5c591343SA. Cody Schuffelen                                     //     avoid large intermediate buffers.
737*5c591343SA. Cody Schuffelen     UINT16           blocks         // IN: If non-zero, this is the maximum number
738*5c591343SA. Cody Schuffelen                                     //     of blocks to be returned, regardless
739*5c591343SA. Cody Schuffelen                                     //     of sizeInBits
740*5c591343SA. Cody Schuffelen     )
741*5c591343SA. Cody Schuffelen {
742*5c591343SA. Cody Schuffelen     UINT32                   counter = 0;       // counter value
743*5c591343SA. Cody Schuffelen     INT16                    bytes;             // number of bytes to produce
744*5c591343SA. Cody Schuffelen     UINT16                   generated;         // number of bytes generated
745*5c591343SA. Cody Schuffelen     BYTE                    *stream = keyStream;
746*5c591343SA. Cody Schuffelen     HMAC_STATE               hState;
747*5c591343SA. Cody Schuffelen     UINT16                   digestSize = CryptHashGetDigestSize(hashAlg);
748*5c591343SA. Cody Schuffelen 
749*5c591343SA. Cody Schuffelen     pAssert(key != NULL && keyStream != NULL);
750*5c591343SA. Cody Schuffelen 
751*5c591343SA. Cody Schuffelen     TEST(TPM_ALG_KDF1_SP800_108);
752*5c591343SA. Cody Schuffelen 
753*5c591343SA. Cody Schuffelen     if(digestSize == 0)
754*5c591343SA. Cody Schuffelen         return 0;
755*5c591343SA. Cody Schuffelen 
756*5c591343SA. Cody Schuffelen     if(counterInOut != NULL)
757*5c591343SA. Cody Schuffelen         counter = *counterInOut;
758*5c591343SA. Cody Schuffelen 
759*5c591343SA. Cody Schuffelen     // If the size of the request is larger than the numbers will handle,
760*5c591343SA. Cody Schuffelen     // it is a fatal error.
761*5c591343SA. Cody Schuffelen     pAssert(((sizeInBits + 7) / 8) <= INT16_MAX);
762*5c591343SA. Cody Schuffelen 
763*5c591343SA. Cody Schuffelen     // The number of bytes to be generated is the smaller of the sizeInBits bytes or
764*5c591343SA. Cody Schuffelen     // the number of requested blocks. The number of blocks is the smaller of the
765*5c591343SA. Cody Schuffelen     // number requested or the number allowed by sizeInBits. A partial block is
766*5c591343SA. Cody Schuffelen     // a full block.
767*5c591343SA. Cody Schuffelen     bytes = (blocks > 0) ? blocks * digestSize : (UINT16)BITS_TO_BYTES(sizeInBits);
768*5c591343SA. Cody Schuffelen     generated = bytes;
769*5c591343SA. Cody Schuffelen 
770*5c591343SA. Cody Schuffelen     // Generate required bytes
771*5c591343SA. Cody Schuffelen     for(; bytes > 0; bytes -= digestSize)
772*5c591343SA. Cody Schuffelen     {
773*5c591343SA. Cody Schuffelen         counter++;
774*5c591343SA. Cody Schuffelen         // Start HMAC
775*5c591343SA. Cody Schuffelen         if(CryptHmacStart(&hState, hashAlg, key->size, key->buffer) == 0)
776*5c591343SA. Cody Schuffelen             return 0;
777*5c591343SA. Cody Schuffelen         // Adding counter
778*5c591343SA. Cody Schuffelen         CryptDigestUpdateInt(&hState.hashState, 4, counter);
779*5c591343SA. Cody Schuffelen 
780*5c591343SA. Cody Schuffelen         // Adding label
781*5c591343SA. Cody Schuffelen         if(label != NULL)
782*5c591343SA. Cody Schuffelen             HASH_DATA(&hState.hashState, label->size, (BYTE *)label->buffer);
783*5c591343SA. Cody Schuffelen         // Add a null. SP108 is not very clear about when the 0 is needed but to
784*5c591343SA. Cody Schuffelen         // make this like the previous version that did not add an 0x00 after
785*5c591343SA. Cody Schuffelen         // a null-terminated string, this version will only add a null byte
786*5c591343SA. Cody Schuffelen         // if the label parameter did not end in a null byte, or if no label
787*5c591343SA. Cody Schuffelen         // is present.
788*5c591343SA. Cody Schuffelen         if((label == NULL)
789*5c591343SA. Cody Schuffelen            || (label->size == 0)
790*5c591343SA. Cody Schuffelen            || (label->buffer[label->size - 1] != 0))
791*5c591343SA. Cody Schuffelen             CryptDigestUpdateInt(&hState.hashState, 1, 0);
792*5c591343SA. Cody Schuffelen         // Adding contextU
793*5c591343SA. Cody Schuffelen         if(contextU != NULL)
794*5c591343SA. Cody Schuffelen             HASH_DATA(&hState.hashState, contextU->size, contextU->buffer);
795*5c591343SA. Cody Schuffelen         // Adding contextV
796*5c591343SA. Cody Schuffelen         if(contextV != NULL)
797*5c591343SA. Cody Schuffelen             HASH_DATA(&hState.hashState, contextV->size, contextV->buffer);
798*5c591343SA. Cody Schuffelen         // Adding size in bits
799*5c591343SA. Cody Schuffelen         CryptDigestUpdateInt(&hState.hashState, 4, sizeInBits);
800*5c591343SA. Cody Schuffelen 
801*5c591343SA. Cody Schuffelen         // Complete and put the data in the buffer
802*5c591343SA. Cody Schuffelen         CryptHmacEnd(&hState, bytes, stream);
803*5c591343SA. Cody Schuffelen         stream = &stream[digestSize];
804*5c591343SA. Cody Schuffelen     }
805*5c591343SA. Cody Schuffelen     // Masking in the KDF is disabled. If the calling function wants something
806*5c591343SA. Cody Schuffelen     // less than even number of bytes, then the caller should do the masking
807*5c591343SA. Cody Schuffelen     // because there is no universal way to do it here
808*5c591343SA. Cody Schuffelen     if(counterInOut != NULL)
809*5c591343SA. Cody Schuffelen         *counterInOut = counter;
810*5c591343SA. Cody Schuffelen     return generated;
811*5c591343SA. Cody Schuffelen }
812*5c591343SA. Cody Schuffelen 
813*5c591343SA. Cody Schuffelen //*** CryptKDFe()
814*5c591343SA. Cody Schuffelen // This function implements KDFe() as defined in TPM specification part 1.
815*5c591343SA. Cody Schuffelen //
816*5c591343SA. Cody Schuffelen // This function returns the number of bytes generated which may be zero.
817*5c591343SA. Cody Schuffelen //
818*5c591343SA. Cody Schuffelen // The 'Z' and 'keyStream' pointers are not allowed to be NULL. The other
819*5c591343SA. Cody Schuffelen // pointer values may be NULL. The value of 'sizeInBits' must be no larger
820*5c591343SA. Cody Schuffelen // than (2^18)-1 = 256K bits (32385 bytes).
821*5c591343SA. Cody Schuffelen // Any error in the processing of this command is considered fatal.
822*5c591343SA. Cody Schuffelen //  Return Type: UINT16
823*5c591343SA. Cody Schuffelen //     0            hash algorithm is not supported or is TPM_ALG_NULL
824*5c591343SA. Cody Schuffelen //    > 0           the number of bytes in the 'keyStream' buffer
825*5c591343SA. Cody Schuffelen //
826*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptKDFe(TPM_ALG_ID hashAlg,TPM2B * Z,const TPM2B * label,TPM2B * partyUInfo,TPM2B * partyVInfo,UINT32 sizeInBits,BYTE * keyStream)827*5c591343SA. Cody Schuffelen CryptKDFe(
828*5c591343SA. Cody Schuffelen     TPM_ALG_ID       hashAlg,       // IN: hash algorithm used in HMAC
829*5c591343SA. Cody Schuffelen     TPM2B           *Z,             // IN: Z
830*5c591343SA. Cody Schuffelen     const TPM2B     *label,         // IN: a label value for the KDF
831*5c591343SA. Cody Schuffelen     TPM2B           *partyUInfo,    // IN: PartyUInfo
832*5c591343SA. Cody Schuffelen     TPM2B           *partyVInfo,    // IN: PartyVInfo
833*5c591343SA. Cody Schuffelen     UINT32           sizeInBits,    // IN: size of generated key in bits
834*5c591343SA. Cody Schuffelen     BYTE            *keyStream      // OUT: key buffer
835*5c591343SA. Cody Schuffelen     )
836*5c591343SA. Cody Schuffelen {
837*5c591343SA. Cody Schuffelen     HASH_STATE       hashState;
838*5c591343SA. Cody Schuffelen     PHASH_DEF        hashDef = CryptGetHashDef(hashAlg);
839*5c591343SA. Cody Schuffelen 
840*5c591343SA. Cody Schuffelen     UINT32           counter = 0;       // counter value
841*5c591343SA. Cody Schuffelen     UINT16           hLen;
842*5c591343SA. Cody Schuffelen     BYTE            *stream = keyStream;
843*5c591343SA. Cody Schuffelen     INT16            bytes;             // number of bytes to generate
844*5c591343SA. Cody Schuffelen 
845*5c591343SA. Cody Schuffelen     pAssert(keyStream != NULL && Z != NULL && ((sizeInBits + 7) / 8) < INT16_MAX);
846*5c591343SA. Cody Schuffelen //
847*5c591343SA. Cody Schuffelen     hLen = hashDef->digestSize;
848*5c591343SA. Cody Schuffelen     bytes = (INT16)((sizeInBits + 7) / 8);
849*5c591343SA. Cody Schuffelen     if(hashAlg == TPM_ALG_NULL || bytes == 0)
850*5c591343SA. Cody Schuffelen         return 0;
851*5c591343SA. Cody Schuffelen 
852*5c591343SA. Cody Schuffelen     // Generate required bytes
853*5c591343SA. Cody Schuffelen     //The inner loop of that KDF uses:
854*5c591343SA. Cody Schuffelen     //  Hash[i] := H(counter | Z | OtherInfo) (5)
855*5c591343SA. Cody Schuffelen     // Where:
856*5c591343SA. Cody Schuffelen     //  Hash[i]         the hash generated on the i-th iteration of the loop.
857*5c591343SA. Cody Schuffelen     //  H()             an approved hash function
858*5c591343SA. Cody Schuffelen     //  counter         a 32-bit counter that is initialized to 1 and incremented
859*5c591343SA. Cody Schuffelen     //                  on each iteration
860*5c591343SA. Cody Schuffelen     //  Z               the X coordinate of the product of a public ECC key and a
861*5c591343SA. Cody Schuffelen     //                  different private ECC key.
862*5c591343SA. Cody Schuffelen     //  OtherInfo       a collection of qualifying data for the KDF defined below.
863*5c591343SA. Cody Schuffelen     //  In this specification, OtherInfo will be constructed by:
864*5c591343SA. Cody Schuffelen     //      OtherInfo := Use | PartyUInfo  | PartyVInfo
865*5c591343SA. Cody Schuffelen     for(; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen)
866*5c591343SA. Cody Schuffelen     {
867*5c591343SA. Cody Schuffelen         if(bytes < hLen)
868*5c591343SA. Cody Schuffelen             hLen = bytes;
869*5c591343SA. Cody Schuffelen         counter++;
870*5c591343SA. Cody Schuffelen         // Do the hash
871*5c591343SA. Cody Schuffelen         CryptHashStart(&hashState, hashAlg);
872*5c591343SA. Cody Schuffelen         // Add counter
873*5c591343SA. Cody Schuffelen         CryptDigestUpdateInt(&hashState, 4, counter);
874*5c591343SA. Cody Schuffelen 
875*5c591343SA. Cody Schuffelen         // Add Z
876*5c591343SA. Cody Schuffelen         if(Z != NULL)
877*5c591343SA. Cody Schuffelen             CryptDigestUpdate2B(&hashState, Z);
878*5c591343SA. Cody Schuffelen         // Add label
879*5c591343SA. Cody Schuffelen         if(label != NULL)
880*5c591343SA. Cody Schuffelen             CryptDigestUpdate2B(&hashState, label);
881*5c591343SA. Cody Schuffelen         // Add a null. SP108 is not very clear about when the 0 is needed but to
882*5c591343SA. Cody Schuffelen         // make this like the previous version that did not add an 0x00 after
883*5c591343SA. Cody Schuffelen         // a null-terminated string, this version will only add a null byte
884*5c591343SA. Cody Schuffelen         // if the label parameter did not end in a null byte, or if no label
885*5c591343SA. Cody Schuffelen         // is present.
886*5c591343SA. Cody Schuffelen         if((label == NULL)
887*5c591343SA. Cody Schuffelen            || (label->size == 0)
888*5c591343SA. Cody Schuffelen            || (label->buffer[label->size - 1] != 0))
889*5c591343SA. Cody Schuffelen             CryptDigestUpdateInt(&hashState, 1, 0);
890*5c591343SA. Cody Schuffelen         // Add PartyUInfo
891*5c591343SA. Cody Schuffelen         if(partyUInfo != NULL)
892*5c591343SA. Cody Schuffelen             CryptDigestUpdate2B(&hashState, partyUInfo);
893*5c591343SA. Cody Schuffelen 
894*5c591343SA. Cody Schuffelen         // Add PartyVInfo
895*5c591343SA. Cody Schuffelen         if(partyVInfo != NULL)
896*5c591343SA. Cody Schuffelen             CryptDigestUpdate2B(&hashState, partyVInfo);
897*5c591343SA. Cody Schuffelen 
898*5c591343SA. Cody Schuffelen         // Compute Hash. hLen was changed to be the smaller of bytes or hLen
899*5c591343SA. Cody Schuffelen         // at the start of each iteration.
900*5c591343SA. Cody Schuffelen         CryptHashEnd(&hashState, hLen, stream);
901*5c591343SA. Cody Schuffelen     }
902*5c591343SA. Cody Schuffelen 
903*5c591343SA. Cody Schuffelen     // Mask off bits if the required bits is not a multiple of byte size
904*5c591343SA. Cody Schuffelen     if((sizeInBits % 8) != 0)
905*5c591343SA. Cody Schuffelen         keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
906*5c591343SA. Cody Schuffelen 
907*5c591343SA. Cody Schuffelen     return (UINT16)((sizeInBits + 7) / 8);
908*5c591343SA. Cody Schuffelen }