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 }