1 /********************************************************************************/
2 /*										*/
3 /*			    TSS Primary API for TPM 2.0				*/
4 /*			     Written by Ken Goldman				*/
5 /*		       IBM Thomas J. Watson Research Center			*/
6 /*										*/
7 /* (c) Copyright IBM Corporation 2018 - 2020					*/
8 /*										*/
9 /* All rights reserved.								*/
10 /* 										*/
11 /* Redistribution and use in source and binary forms, with or without		*/
12 /* modification, are permitted provided that the following conditions are	*/
13 /* met:										*/
14 /* 										*/
15 /* Redistributions of source code must retain the above copyright notice,	*/
16 /* this list of conditions and the following disclaimer.			*/
17 /* 										*/
18 /* Redistributions in binary form must reproduce the above copyright		*/
19 /* notice, this list of conditions and the following disclaimer in the		*/
20 /* documentation and/or other materials provided with the distribution.		*/
21 /* 										*/
22 /* Neither the names of the IBM Corporation nor the names of its		*/
23 /* contributors may be used to endorse or promote products derived from		*/
24 /* this software without specific prior written permission.			*/
25 /* 										*/
26 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS		*/
27 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT		*/
28 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR	*/
29 /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT		*/
30 /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,	*/
31 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT		*/
32 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,	*/
33 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY	*/
34 /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT		*/
35 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE	*/
36 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.		*/
37 /********************************************************************************/
38 
39 #include <stdlib.h>
40 #include <string.h>
41 #include <stdarg.h>
42 #include <errno.h>
43 
44 #ifdef TPM_POSIX
45 #include <netinet/in.h>
46 #endif
47 #ifdef TPM_WINDOWS
48 #include <winsock2.h>
49 #endif
50 
51 #include "tssauth.h"
52 #include "tssauth20.h"
53 #include <ibmtss/tss.h>
54 #include "tssproperties.h"
55 #include <ibmtss/tsstransmit.h>
56 #include <ibmtss/tssutils.h>
57 #include <ibmtss/tssresponsecode.h>
58 #include <ibmtss/tssmarshal.h>
59 #include <ibmtss/Unmarshal_fp.h>
60 #include "tssccattributes.h"
61 #ifndef TPM_TSS_NOCRYPTO
62 #include <ibmtss/tsscrypto.h>
63 #include <ibmtss/tsscryptoh.h>
64 #endif
65 #include <ibmtss/tssprintcmd.h>
66 #include "tss20.h"
67 
68 /* Files:
69 
70    h01xxxxxx.bin - NV index name
71    h02xxxxxx.bin - hmac session context
72    h03xxxxxx.bin - policy session context
73    h80xxxxxx.bin - transient object name
74 
75    cxxxx...xxxx.bin - context blob name
76 */
77 
78 /* NOTE Synchronize with
79 
80    TSS_HmacSession_InitContext
81    TSS_HmacSession_Unmarshal
82    TSS_HmacSession_Marshal
83 */
84 
85 struct TSS_HMAC_CONTEXT {
86     TPMI_SH_AUTH_SESSION	sessionHandle;		/* the session handle */
87     TPMI_ALG_HASH		authHashAlg;		/* hash algorithm to use for the session */
88 #ifndef TPM_TSS_NOCRYPTO
89     uint32_t           		sizeInBytes;		/* hash algorithm mapped to size */
90 #endif	/* TPM_TSS_NOCRYPTO */
91     TPMT_SYM_DEF 		symmetric;		/* the algorithm and key size for parameter
92 							   encryption */
93     TPMI_DH_ENTITY 		bind;			/* bind handle */
94     TPM2B_NAME			bindName;		/* Name corresponding to the the bind
95 							   handle */
96     TPM2B_AUTH			bindAuthValue;		/* password corresponding to the bind
97 							   handle */
98 #ifndef TPM_TSS_NOCRYPTO
99     TPM2B_NONCE 		nonceTPM;		/* from TPM in response */
100     TPM2B_NONCE			nonceCaller;		/* from caller in command */
101     TPM2B_DIGEST		sessionKey;		/* from KDFa at session creation */
102 #endif	/* TPM_TSS_NOCRYPTO */
103     TPM_SE			sessionType;		/* HMAC (0), policy (1), or trial policy */
104     uint8_t			isPasswordNeeded;	/* flag set by policy password */
105     uint8_t			isAuthValueNeeded;	/* flag set by policy authvalue */
106     /* Items below this line are for the lifetime of one command.  They are not saved and loaded. */
107     TPM2B_KEY			hmacKey;		/* HMAC key calculated for each command */
108 #ifndef TPM_TSS_NOCRYPTO
109     TPM2B_KEY			sessionValue;		/* KDFa secret for parameter encryption */
110 #endif	/* TPM_TSS_NOCRYPTO */
111 } TSS_HMAC_CONTEXT;
112 
113 /* functions for command pre- and post- processing */
114 
115 typedef TPM_RC (*TSS_PreProcessFunction_t)(TSS_CONTEXT *tssContext,
116 					   COMMAND_PARAMETERS *in,
117 					   EXTRA_PARAMETERS *extra);
118 typedef TPM_RC (*TSS_ChangeAuthFunction_t)(TSS_CONTEXT *tssContext,
119 					   struct TSS_HMAC_CONTEXT *session,
120 					   size_t handleNumber,
121 					   COMMAND_PARAMETERS *in);
122 typedef TPM_RC (*TSS_PostProcessFunction_t)(TSS_CONTEXT *tssContext,
123 					    COMMAND_PARAMETERS *in,
124 					    RESPONSE_PARAMETERS *out,
125 					    EXTRA_PARAMETERS *extra);
126 
127 static TPM_RC TSS_PR_StartAuthSession(TSS_CONTEXT *tssContext,
128 				      StartAuthSession_In *in,
129 				      StartAuthSession_Extra *extra);
130 static TPM_RC TSS_PR_NV_DefineSpace(TSS_CONTEXT *tssContext,
131 				    NV_DefineSpace_In *in,
132 				    void *extra);
133 
134 static TPM_RC TSS_CA_HierarchyChangeAuth(TSS_CONTEXT *tssContext,
135 					 struct TSS_HMAC_CONTEXT *session,
136 					 size_t handleNumber,
137 					 HierarchyChangeAuth_In *in);
138 static TPM_RC TSS_CA_NV_UndefineSpaceSpecial(TSS_CONTEXT *tssContext,
139 					     struct TSS_HMAC_CONTEXT *session,
140 					     size_t handleNumber,
141 					     NV_UndefineSpaceSpecial_In *in);
142 static TPM_RC TSS_CA_NV_ChangeAuth(TSS_CONTEXT *tssContext,
143 				   struct TSS_HMAC_CONTEXT *session,
144 				   size_t handleNumber,
145 				   NV_ChangeAuth_In *in);
146 
147 
148 static TPM_RC TSS_PO_StartAuthSession(TSS_CONTEXT *tssContext,
149 				      StartAuthSession_In *in,
150 				      StartAuthSession_Out *out,
151 				      StartAuthSession_Extra *extra);
152 static TPM_RC TSS_PO_ContextSave(TSS_CONTEXT *tssContext,
153 				 ContextSave_In *in,
154 				 ContextSave_Out *out,
155 				 void *extra);
156 static TPM_RC TSS_PO_ContextLoad(TSS_CONTEXT *tssContext,
157 				 ContextLoad_In *in,
158 				 ContextLoad_Out *out,
159 				 void *extra);
160 static TPM_RC TSS_PO_FlushContext(TSS_CONTEXT *tssContext,
161 				  FlushContext_In *in,
162 				  void *out,
163 				  void *extra);
164 static TPM_RC TSS_PO_EvictControl(TSS_CONTEXT *tssContext,
165 				  EvictControl_In *in,
166 				  void *out,
167 				  void *extra);
168 static TPM_RC TSS_PO_Load(TSS_CONTEXT *tssContext,
169 			  Load_In *in,
170 			  Load_Out *out,
171 			  void *extra);
172 static TPM_RC TSS_PO_LoadExternal(TSS_CONTEXT *tssContext,
173 				  LoadExternal_In *in,
174 				  LoadExternal_Out *out,
175 				  void *extra);
176 static TPM_RC TSS_PO_ReadPublic(TSS_CONTEXT *tssContext,
177 				ReadPublic_In *in,
178 				ReadPublic_Out *out,
179 				void *extra);
180 static TPM_RC TSS_PO_CreateLoaded(TSS_CONTEXT *tssContext,
181 				  CreateLoaded_In *in,
182 				  CreateLoaded_Out *out,
183 				  void *extra);
184 static TPM_RC TSS_PO_HMAC_Start(TSS_CONTEXT *tssContext,
185 				HMAC_Start_In *in,
186 				HMAC_Start_Out *out,
187 				void *extra);
188 static TPM_RC TSS_PO_HashSequenceStart(TSS_CONTEXT *tssContext,
189 				       HashSequenceStart_In *in,
190 				       HashSequenceStart_Out *out,
191 				       void *extra);
192 static TPM_RC TSS_PO_SequenceComplete(TSS_CONTEXT *tssContext,
193 				      SequenceComplete_In *in,
194 				      SequenceComplete_Out *out,
195 				      void *extra);
196 static TPM_RC TSS_PO_EventSequenceComplete(TSS_CONTEXT *tssContext,
197 					   EventSequenceComplete_In *in,
198 					   EventSequenceComplete_Out *out,
199 					   void *extra);
200 static TPM_RC TSS_PO_PolicyAuthValue(TSS_CONTEXT *tssContext,
201 				     PolicyAuthValue_In *in,
202 				     void *out,
203 				     void *extra);
204 static TPM_RC TSS_PO_PolicyPassword(TSS_CONTEXT *tssContext,
205 				    PolicyPassword_In *in,
206 				    void *out,
207 				    void *extra);
208 static TPM_RC TSS_PO_CreatePrimary(TSS_CONTEXT *tssContext,
209 				   CreatePrimary_In *in,
210 				   CreatePrimary_Out *out,
211 				   void *extra);
212 static TPM_RC TSS_PO_NV_DefineSpace(TSS_CONTEXT *tssContext,
213 				    NV_DefineSpace_In *in,
214 				    void *out,
215 				    void *extra);
216 static TPM_RC TSS_PO_NV_ReadPublic(TSS_CONTEXT *tssContext,
217 				   NV_ReadPublic_In *in,
218 				   NV_ReadPublic_Out *out,
219 				   void *extra);
220 static TPM_RC TSS_PO_NV_UndefineSpace(TSS_CONTEXT *tssContext,
221 				      NV_UndefineSpace_In *in,
222 				      void *out,
223 				      void *extra);
224 static TPM_RC TSS_PO_NV_UndefineSpaceSpecial(TSS_CONTEXT *tssContext,
225 					     NV_UndefineSpaceSpecial_In *in,
226 					     void *out,
227 					     void *extra);
228 static TPM_RC TSS_PO_NV_Write(TSS_CONTEXT *tssContext,
229 			      NV_Write_In *in,
230 			      void *out,
231 			      void *extra);
232 static TPM_RC TSS_PO_NV_WriteLock(TSS_CONTEXT *tssContext,
233 				  NV_WriteLock_In *in,
234 				  void *out,
235 				  void *extra);
236 static TPM_RC TSS_PO_NV_ReadLock(TSS_CONTEXT *tssContext,
237 				 NV_ReadLock_In *in,
238 				 void *out,
239 				 void *extra);
240 
241 typedef struct TSS_TABLE {
242     TPM_CC 			commandCode;
243     TSS_PreProcessFunction_t	preProcessFunction;
244     TSS_ChangeAuthFunction_t	changeAuthFunction;
245     TSS_PostProcessFunction_t 	postProcessFunction;
246 } TSS_TABLE;
247 
248 /* This table indexes from the command to pre- and post- processing functions.  A missing entry is
249    not an error, and indicates a command with no functions. */
250 
251 static const TSS_TABLE tssTable [] = {
252 
253     {TPM_CC_Startup, NULL, NULL, NULL},
254     {TPM_CC_Shutdown, NULL, NULL, NULL},
255     {TPM_CC_SelfTest, NULL, NULL, NULL},
256     {TPM_CC_IncrementalSelfTest, NULL, NULL, NULL},
257     {TPM_CC_GetTestResult, NULL, NULL, NULL},
258     {TPM_CC_StartAuthSession, (TSS_PreProcessFunction_t)TSS_PR_StartAuthSession, NULL, (TSS_PostProcessFunction_t)TSS_PO_StartAuthSession},
259     {TPM_CC_PolicyRestart, NULL, NULL, NULL},
260     {TPM_CC_Create, NULL, NULL, NULL},
261     {TPM_CC_Load, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_Load},
262     {TPM_CC_LoadExternal, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_LoadExternal},
263     {TPM_CC_ReadPublic, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_ReadPublic},
264     {TPM_CC_ActivateCredential, NULL, NULL, NULL},
265     {TPM_CC_MakeCredential, NULL, NULL, NULL},
266     {TPM_CC_Unseal, NULL, NULL, NULL},
267     {TPM_CC_ObjectChangeAuth, NULL, NULL, NULL},
268     {TPM_CC_CreateLoaded, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_CreateLoaded},
269     {TPM_CC_Duplicate, NULL, NULL, NULL},
270     {TPM_CC_Rewrap, NULL, NULL, NULL},
271     {TPM_CC_Import, NULL, NULL, NULL},
272     {TPM_CC_RSA_Encrypt, NULL, NULL, NULL},
273     {TPM_CC_RSA_Decrypt, NULL, NULL, NULL},
274     {TPM_CC_ECDH_KeyGen, NULL, NULL, NULL},
275     {TPM_CC_ECDH_ZGen, NULL, NULL, NULL},
276     {TPM_CC_ECC_Parameters, NULL, NULL, NULL},
277     {TPM_CC_ZGen_2Phase, NULL, NULL, NULL},
278     {TPM_CC_EncryptDecrypt, NULL, NULL, NULL},
279     {TPM_CC_EncryptDecrypt2, NULL, NULL, NULL},
280     {TPM_CC_Hash, NULL, NULL, NULL},
281     {TPM_CC_HMAC, NULL, NULL, NULL},
282     {TPM_CC_GetRandom, NULL, NULL, NULL},
283     {TPM_CC_StirRandom, NULL, NULL, NULL},
284     {TPM_CC_HMAC_Start, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_HMAC_Start},
285     {TPM_CC_HashSequenceStart, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_HashSequenceStart},
286     {TPM_CC_SequenceUpdate, NULL, NULL, NULL},
287     {TPM_CC_SequenceComplete, NULL,NULL, (TSS_PostProcessFunction_t)TSS_PO_SequenceComplete},
288     {TPM_CC_EventSequenceComplete, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_EventSequenceComplete},
289     {TPM_CC_Certify, NULL, NULL, NULL},
290     {TPM_CC_CertifyX509, NULL, NULL, NULL},
291     {TPM_CC_CertifyCreation, NULL, NULL, NULL},
292     {TPM_CC_Quote, NULL, NULL, NULL},
293     {TPM_CC_GetSessionAuditDigest, NULL, NULL, NULL},
294     {TPM_CC_GetCommandAuditDigest, NULL, NULL, NULL},
295     {TPM_CC_GetTime, NULL, NULL, NULL},
296     {TPM_CC_Commit, NULL, NULL, NULL},
297     {TPM_CC_EC_Ephemeral, NULL, NULL, NULL},
298     {TPM_CC_VerifySignature, NULL, NULL, NULL},
299     {TPM_CC_Sign, NULL, NULL, NULL},
300     {TPM_CC_SetCommandCodeAuditStatus, NULL, NULL, NULL},
301     {TPM_CC_PCR_Extend, NULL, NULL, NULL},
302     {TPM_CC_PCR_Event, NULL, NULL, NULL},
303     {TPM_CC_PCR_Read, NULL, NULL, NULL},
304     {TPM_CC_PCR_Allocate, NULL, NULL, NULL},
305     {TPM_CC_PCR_SetAuthPolicy, NULL, NULL, NULL},
306     {TPM_CC_PCR_SetAuthValue, NULL, NULL, NULL},
307     {TPM_CC_PCR_Reset, NULL, NULL, NULL},
308     {TPM_CC_PolicySigned, NULL, NULL, NULL},
309     {TPM_CC_PolicySecret, NULL, NULL, NULL},
310     {TPM_CC_PolicyTicket, NULL, NULL, NULL},
311     {TPM_CC_PolicyOR, NULL, NULL, NULL},
312     {TPM_CC_PolicyPCR, NULL, NULL, NULL},
313     {TPM_CC_PolicyLocality, NULL, NULL, NULL},
314     {TPM_CC_PolicyNV, NULL, NULL, NULL},
315     {TPM_CC_PolicyAuthorizeNV, NULL, NULL, NULL},
316     {TPM_CC_PolicyCounterTimer, NULL, NULL, NULL},
317     {TPM_CC_PolicyCommandCode, NULL, NULL, NULL},
318     {TPM_CC_PolicyPhysicalPresence, NULL, NULL, NULL},
319     {TPM_CC_PolicyCpHash, NULL, NULL, NULL},
320     {TPM_CC_PolicyNameHash, NULL, NULL, NULL},
321     {TPM_CC_PolicyDuplicationSelect, NULL, NULL, NULL},
322     {TPM_CC_PolicyAuthorize, NULL, NULL, NULL},
323     {TPM_CC_PolicyAuthValue, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_PolicyAuthValue},
324     {TPM_CC_PolicyPassword, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_PolicyPassword},
325     {TPM_CC_PolicyGetDigest, NULL, NULL, NULL},
326     {TPM_CC_PolicyNvWritten, NULL, NULL, NULL},
327     {TPM_CC_PolicyTemplate, NULL, NULL, NULL},
328     {TPM_CC_CreatePrimary, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_CreatePrimary},
329     {TPM_CC_HierarchyControl, NULL, NULL, NULL},
330     {TPM_CC_SetPrimaryPolicy, NULL, NULL, NULL},
331     {TPM_CC_ChangePPS, NULL, NULL, NULL},
332     {TPM_CC_ChangeEPS, NULL, NULL, NULL},
333     {TPM_CC_Clear, NULL, NULL, NULL},
334     {TPM_CC_ClearControl, NULL, NULL, NULL},
335     {TPM_CC_HierarchyChangeAuth, NULL, (TSS_ChangeAuthFunction_t)TSS_CA_HierarchyChangeAuth, NULL},
336     {TPM_CC_DictionaryAttackLockReset, NULL, NULL, NULL},
337     {TPM_CC_DictionaryAttackParameters, NULL, NULL, NULL},
338     {TPM_CC_PP_Commands, NULL, NULL, NULL},
339     {TPM_CC_SetAlgorithmSet, NULL, NULL, NULL},
340     {TPM_CC_ContextSave, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_ContextSave},
341     {TPM_CC_ContextLoad, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_ContextLoad},
342     {TPM_CC_FlushContext, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_FlushContext},
343     {TPM_CC_EvictControl, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_EvictControl},
344     {TPM_CC_ReadClock, NULL, NULL, NULL},
345     {TPM_CC_ClockSet, NULL, NULL, NULL},
346     {TPM_CC_ClockRateAdjust, NULL, NULL, NULL},
347     {TPM_CC_GetCapability, NULL, NULL, NULL},
348     {TPM_CC_TestParms, NULL, NULL, NULL},
349     {TPM_CC_NV_DefineSpace, (TSS_PreProcessFunction_t)TSS_PR_NV_DefineSpace, NULL,  (TSS_PostProcessFunction_t)TSS_PO_NV_DefineSpace},
350     {TPM_CC_NV_UndefineSpace, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_UndefineSpace},
351     {TPM_CC_NV_UndefineSpaceSpecial, NULL, (TSS_ChangeAuthFunction_t)TSS_CA_NV_UndefineSpaceSpecial, (TSS_PostProcessFunction_t)TSS_PO_NV_UndefineSpaceSpecial},
352     {TPM_CC_NV_ReadPublic, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_ReadPublic},
353     {TPM_CC_NV_Write, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_Write},
354     {TPM_CC_NV_Increment, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_Write},
355     {TPM_CC_NV_Extend, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_Write},
356     {TPM_CC_NV_SetBits, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_Write},
357     {TPM_CC_NV_WriteLock, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_WriteLock},
358     {TPM_CC_NV_GlobalWriteLock, NULL, NULL, NULL},
359     {TPM_CC_NV_Read, NULL, NULL, NULL},
360     {TPM_CC_NV_ReadLock, NULL, NULL, (TSS_PostProcessFunction_t)TSS_PO_NV_ReadLock},
361     {TPM_CC_NV_ChangeAuth, NULL, (TSS_ChangeAuthFunction_t)TSS_CA_NV_ChangeAuth, NULL},
362     {TPM_CC_NV_Certify, NULL, NULL, NULL}
363 };
364 
365 #ifndef TPM_TSS_NO_PRINT
366 
367 typedef void (*TSS_InPrintFunction_t)(COMMAND_PARAMETERS *in, unsigned int indent);
368 
369 typedef struct TSS_PRINT_TABLE {
370     TPM_CC 			commandCode;
371     TSS_InPrintFunction_t	inPrintFunction;
372 } TSS_PRINT_TABLE;
373 
374 /* This table indexes from the command to print functions.  A missing entry is
375    not an error, and indicates a command with no function. */
376 
377 static const TSS_PRINT_TABLE tssPrintTable [] = {
378 
379     {TPM_CC_Startup, (TSS_InPrintFunction_t)Startup_In_Print},
380     {TPM_CC_Shutdown, (TSS_InPrintFunction_t)Shutdown_In_Print},
381     {TPM_CC_SelfTest, (TSS_InPrintFunction_t)SelfTest_In_Print},
382     {TPM_CC_IncrementalSelfTest, (TSS_InPrintFunction_t)IncrementalSelfTest_In_Print},
383     {TPM_CC_GetTestResult, NULL},
384     {TPM_CC_StartAuthSession, (TSS_InPrintFunction_t)StartAuthSession_In_Print},
385     {TPM_CC_PolicyRestart, (TSS_InPrintFunction_t)PolicyRestart_In_Print},
386     {TPM_CC_Create,(TSS_InPrintFunction_t)Create_In_Print},
387     {TPM_CC_Load, (TSS_InPrintFunction_t)Load_In_Print},
388     {TPM_CC_LoadExternal, (TSS_InPrintFunction_t)LoadExternal_In_Print},
389     {TPM_CC_ReadPublic, (TSS_InPrintFunction_t)ReadPublic_In_Print},
390     {TPM_CC_ActivateCredential, (TSS_InPrintFunction_t)ActivateCredential_In_Print},
391     {TPM_CC_MakeCredential, (TSS_InPrintFunction_t)MakeCredential_In_Print},
392     {TPM_CC_Unseal, (TSS_InPrintFunction_t)Unseal_In_Print},
393     {TPM_CC_ObjectChangeAuth, (TSS_InPrintFunction_t)ObjectChangeAuth_In_Print},
394     {TPM_CC_CreateLoaded, (TSS_InPrintFunction_t)CreateLoaded_In_Print},
395     {TPM_CC_Duplicate, (TSS_InPrintFunction_t)Duplicate_In_Print},
396     {TPM_CC_Rewrap, (TSS_InPrintFunction_t)Rewrap_In_Print},
397     {TPM_CC_Import, (TSS_InPrintFunction_t)Import_In_Print},
398     {TPM_CC_RSA_Encrypt, (TSS_InPrintFunction_t)RSA_Encrypt_In_Print},
399     {TPM_CC_RSA_Decrypt, (TSS_InPrintFunction_t)RSA_Decrypt_In_Print},
400     {TPM_CC_ECDH_KeyGen, (TSS_InPrintFunction_t)ECDH_KeyGen_In_Print},
401     {TPM_CC_ECDH_ZGen, (TSS_InPrintFunction_t)ECDH_ZGen_In_Print},
402     {TPM_CC_ECC_Parameters, (TSS_InPrintFunction_t)ECC_Parameters_In_Print},
403     {TPM_CC_ZGen_2Phase, (TSS_InPrintFunction_t)ZGen_2Phase_In_Print},
404     {TPM_CC_EncryptDecrypt, (TSS_InPrintFunction_t)EncryptDecrypt_In_Print},
405     {TPM_CC_EncryptDecrypt2, (TSS_InPrintFunction_t)EncryptDecrypt2_In_Print},
406     {TPM_CC_Hash, (TSS_InPrintFunction_t)Hash_In_Print},
407     {TPM_CC_HMAC, (TSS_InPrintFunction_t)HMAC_In_Print},
408     {TPM_CC_GetRandom, (TSS_InPrintFunction_t)GetRandom_In_Print},
409     {TPM_CC_StirRandom, (TSS_InPrintFunction_t)StirRandom_In_Print},
410     {TPM_CC_HMAC_Start, (TSS_InPrintFunction_t)HMAC_Start_In_Print},
411     {TPM_CC_HashSequenceStart, (TSS_InPrintFunction_t)HashSequenceStart_In_Print},
412     {TPM_CC_SequenceUpdate, (TSS_InPrintFunction_t)SequenceUpdate_In_Print},
413     {TPM_CC_SequenceComplete, (TSS_InPrintFunction_t)SequenceComplete_In_Print},
414     {TPM_CC_EventSequenceComplete, (TSS_InPrintFunction_t)EventSequenceComplete_In_Print},
415     {TPM_CC_Certify, (TSS_InPrintFunction_t)Certify_In_Print},
416     {TPM_CC_CertifyX509, (TSS_InPrintFunction_t)CertifyX509_In_Print},
417     {TPM_CC_CertifyCreation, (TSS_InPrintFunction_t)CertifyCreation_In_Print},
418     {TPM_CC_Quote, (TSS_InPrintFunction_t)Quote_In_Print},
419     {TPM_CC_GetSessionAuditDigest, (TSS_InPrintFunction_t)GetSessionAuditDigest_In_Print},
420     {TPM_CC_GetCommandAuditDigest, (TSS_InPrintFunction_t)GetCommandAuditDigest_In_Print},
421     {TPM_CC_GetTime, (TSS_InPrintFunction_t)GetTime_In_Print},
422     {TPM_CC_Commit, (TSS_InPrintFunction_t)Commit_In_Print},
423     {TPM_CC_EC_Ephemeral, (TSS_InPrintFunction_t)EC_Ephemeral_In_Print},
424     {TPM_CC_VerifySignature, (TSS_InPrintFunction_t)VerifySignature_In_Print},
425     {TPM_CC_Sign, (TSS_InPrintFunction_t)Sign_In_Print},
426     {TPM_CC_SetCommandCodeAuditStatus, (TSS_InPrintFunction_t)SetCommandCodeAuditStatus_In_Print},
427     {TPM_CC_PCR_Extend, (TSS_InPrintFunction_t)PCR_Extend_In_Print},
428     {TPM_CC_PCR_Event, (TSS_InPrintFunction_t)PCR_Event_In_Print},
429     {TPM_CC_PCR_Read, (TSS_InPrintFunction_t)PCR_Read_In_Print},
430     {TPM_CC_PCR_Allocate, (TSS_InPrintFunction_t)PCR_Allocate_In_Print},
431     {TPM_CC_PCR_SetAuthPolicy, (TSS_InPrintFunction_t)PCR_SetAuthPolicy_In_Print},
432     {TPM_CC_PCR_SetAuthValue, (TSS_InPrintFunction_t)PCR_SetAuthValue_In_Print},
433     {TPM_CC_PCR_Reset, (TSS_InPrintFunction_t)PCR_Reset_In_Print},
434     {TPM_CC_PolicySigned, (TSS_InPrintFunction_t)PolicySigned_In_Print},
435     {TPM_CC_PolicySecret, (TSS_InPrintFunction_t)PolicySecret_In_Print},
436     {TPM_CC_PolicyTicket, (TSS_InPrintFunction_t)PolicyTicket_In_Print},
437     {TPM_CC_PolicyOR, (TSS_InPrintFunction_t)PolicyOR_In_Print},
438     {TPM_CC_PolicyPCR, (TSS_InPrintFunction_t)PolicyPCR_In_Print},
439     {TPM_CC_PolicyLocality, (TSS_InPrintFunction_t)PolicyLocality_In_Print},
440     {TPM_CC_PolicyNV, (TSS_InPrintFunction_t)PolicyNV_In_Print},
441     {TPM_CC_PolicyAuthorizeNV, (TSS_InPrintFunction_t)PolicyAuthorizeNV_In_Print},
442     {TPM_CC_PolicyCounterTimer, (TSS_InPrintFunction_t)PolicyCounterTimer_In_Print},
443     {TPM_CC_PolicyCommandCode, (TSS_InPrintFunction_t)PolicyCommandCode_In_Print},
444     {TPM_CC_PolicyPhysicalPresence, (TSS_InPrintFunction_t)PolicyPhysicalPresence_In_Print},
445     {TPM_CC_PolicyCpHash, (TSS_InPrintFunction_t)PolicyCpHash_In_Print},
446     {TPM_CC_PolicyNameHash, (TSS_InPrintFunction_t)PolicyNameHash_In_Print},
447     {TPM_CC_PolicyDuplicationSelect, (TSS_InPrintFunction_t)PolicyDuplicationSelect_In_Print},
448     {TPM_CC_PolicyAuthorize, (TSS_InPrintFunction_t)PolicyAuthorize_In_Print},
449     {TPM_CC_PolicyAuthValue, (TSS_InPrintFunction_t)PolicyAuthValue_In_Print},
450     {TPM_CC_PolicyPassword, (TSS_InPrintFunction_t)PolicyPassword_In_Print},
451     {TPM_CC_PolicyGetDigest, (TSS_InPrintFunction_t)PolicyGetDigest_In_Print},
452     {TPM_CC_PolicyNvWritten, (TSS_InPrintFunction_t)PolicyNvWritten_In_Print},
453     {TPM_CC_PolicyTemplate, (TSS_InPrintFunction_t)PolicyTemplate_In_Print},
454     {TPM_CC_CreatePrimary, (TSS_InPrintFunction_t)CreatePrimary_In_Print},
455     {TPM_CC_HierarchyControl, (TSS_InPrintFunction_t)HierarchyControl_In_Print},
456     {TPM_CC_SetPrimaryPolicy, (TSS_InPrintFunction_t)SetPrimaryPolicy_In_Print},
457     {TPM_CC_ChangePPS, (TSS_InPrintFunction_t)ChangePPS_In_Print},
458     {TPM_CC_ChangeEPS, (TSS_InPrintFunction_t)ChangeEPS_In_Print},
459     {TPM_CC_Clear, (TSS_InPrintFunction_t)Clear_In_Print},
460     {TPM_CC_ClearControl, (TSS_InPrintFunction_t)ClearControl_In_Print},
461     {TPM_CC_HierarchyChangeAuth, (TSS_InPrintFunction_t)HierarchyChangeAuth_In_Print},
462     {TPM_CC_DictionaryAttackLockReset, (TSS_InPrintFunction_t)DictionaryAttackLockReset_In_Print},
463     {TPM_CC_DictionaryAttackParameters, (TSS_InPrintFunction_t)DictionaryAttackParameters_In_Print},
464     {TPM_CC_PP_Commands, (TSS_InPrintFunction_t)PP_Commands_In_Print},
465     {TPM_CC_SetAlgorithmSet, (TSS_InPrintFunction_t)SetAlgorithmSet_In_Print},
466     {TPM_CC_ContextSave, (TSS_InPrintFunction_t)ContextSave_In_Print},
467     {TPM_CC_ContextLoad, (TSS_InPrintFunction_t)ContextLoad_In_Print},
468     {TPM_CC_FlushContext, (TSS_InPrintFunction_t)FlushContext_In_Print},
469     {TPM_CC_EvictControl, (TSS_InPrintFunction_t)EvictControl_In_Print},
470     {TPM_CC_ReadClock, (TSS_InPrintFunction_t)NULL},
471     {TPM_CC_ClockSet, (TSS_InPrintFunction_t)ClockSet_In_Print},
472     {TPM_CC_ClockRateAdjust, (TSS_InPrintFunction_t)ClockRateAdjust_In_Print},
473     {TPM_CC_GetCapability, (TSS_InPrintFunction_t)GetCapability_In_Print},
474     {TPM_CC_TestParms, (TSS_InPrintFunction_t)TestParms_In_Print},
475     {TPM_CC_NV_DefineSpace, (TSS_InPrintFunction_t)NV_DefineSpace_In_Print},
476     {TPM_CC_NV_UndefineSpace, (TSS_InPrintFunction_t)NV_UndefineSpace_In_Print},
477     {TPM_CC_NV_UndefineSpaceSpecial, (TSS_InPrintFunction_t)NV_UndefineSpaceSpecial_In_Print},
478     {TPM_CC_NV_ReadPublic, (TSS_InPrintFunction_t)NV_ReadPublic_In_Print},
479     {TPM_CC_NV_Write, (TSS_InPrintFunction_t)NV_Write_In_Print},
480     {TPM_CC_NV_Increment, (TSS_InPrintFunction_t)NV_Increment_In_Print},
481     {TPM_CC_NV_Extend, (TSS_InPrintFunction_t)NV_Extend_In_Print},
482     {TPM_CC_NV_SetBits, (TSS_InPrintFunction_t)NV_SetBits_In_Print},
483     {TPM_CC_NV_WriteLock, (TSS_InPrintFunction_t)NV_WriteLock_In_Print},
484     {TPM_CC_NV_GlobalWriteLock, (TSS_InPrintFunction_t)NV_GlobalWriteLock_In_Print},
485     {TPM_CC_NV_Read, (TSS_InPrintFunction_t)NV_Read_In_Print},
486     {TPM_CC_NV_ReadLock, (TSS_InPrintFunction_t)NV_ReadLock_In_Print},
487     {TPM_CC_NV_ChangeAuth, (TSS_InPrintFunction_t)NV_ChangeAuth_In_Print},
488     {TPM_CC_NV_Certify, (TSS_InPrintFunction_t)NV_Certify_In_Print}
489 };
490 
491 #endif /* TPM_TSS_NO_PRINT */
492 
493 /* local prototypes */
494 
495 static TPM_RC TSS_Execute_valist(TSS_CONTEXT *tssContext,
496 				 COMMAND_PARAMETERS *in,
497 				 va_list ap);
498 
499 
500 static TPM_RC TSS_PwapSession_Set(TPMS_AUTH_COMMAND *authCommand,
501 				  const char *password);
502 static TPM_RC TSS_PwapSession_Verify(TPMS_AUTH_RESPONSE *authResponse);
503 
504 static TPM_RC TSS_HmacSession_GetContext(struct TSS_HMAC_CONTEXT **session);
505 static void   TSS_HmacSession_InitContext(struct TSS_HMAC_CONTEXT *session);
506 static void   TSS_HmacSession_FreeContext(struct TSS_HMAC_CONTEXT *session);
507 
508 #ifndef TPM_TSS_NOCRYPTO
509 static TPM_RC TSS_HmacSession_SetSessionKey(TSS_CONTEXT *tssContext,
510 					    struct TSS_HMAC_CONTEXT *session,
511 					    TPM2B_DIGEST *salt,
512 					    TPMI_DH_ENTITY bind,
513 					    TPM2B_AUTH *bindAuthValue);
514 static TPM_RC TSS_HmacSession_SetNonceCaller(struct TSS_HMAC_CONTEXT *session,
515 					     TPMS_AUTH_COMMAND 	*authC);
516 static TPM_RC TSS_HmacSession_SetHmacKey(TSS_CONTEXT *tssContext,
517 					 struct TSS_HMAC_CONTEXT *session,
518 					 size_t handleNumber,
519 					 const char *password);
520 #endif	/* TPM_TSS_NOCRYPTO */
521 static TPM_RC TSS_HmacSession_SetHMAC(TSS_AUTH_CONTEXT *tssAuthContext,
522 				      struct TSS_HMAC_CONTEXT *session[],
523 				      TPMS_AUTH_COMMAND *authCommand[],
524 				      TPMI_SH_AUTH_SESSION sessionHandle[],
525 				      unsigned int sessionAttributes[],
526 				      const char *password[],
527 				      TPM2B_NAME *name0,
528 				      TPM2B_NAME *name1,
529 				      TPM2B_NAME *name2);
530 #ifndef TPM_TSS_NOCRYPTO
531 static TPM_RC TSS_HmacSession_Verify(TSS_AUTH_CONTEXT *tssAuthContext,
532 				     struct TSS_HMAC_CONTEXT *session,
533 				     TPMS_AUTH_RESPONSE *authResponse);
534 #endif	/* TPM_TSS_NOCRYPTO */
535 static TPM_RC TSS_HmacSession_Continue(TSS_CONTEXT *tssContext,
536 				       struct TSS_HMAC_CONTEXT *session,
537 				       TPMS_AUTH_RESPONSE *authR);
538 
539 
540 static TPM_RC TSS_HmacSession_SaveSession(TSS_CONTEXT *tssContext,
541 					  struct TSS_HMAC_CONTEXT *session);
542 static TPM_RC TSS_HmacSession_LoadSession(TSS_CONTEXT *tssContext,
543 					  struct TSS_HMAC_CONTEXT *session,
544 					  TPMI_SH_AUTH_SESSION	sessionHandle);
545 #ifdef TPM_TSS_NOFILE
546 static TPM_RC TSS_HmacSession_SaveData(TSS_CONTEXT *tssContext,
547 				       TPMI_SH_AUTH_SESSION sessionHandle,
548 				       uint32_t outLength,
549 				       uint8_t *outBuffer);
550 static TPM_RC TSS_HmacSession_LoadData(TSS_CONTEXT *tssContext,
551 				       uint32_t *inLength, uint8_t **inData,
552 				       TPMI_SH_AUTH_SESSION sessionHandle);
553 static TPM_RC TSS_HmacSession_DeleteData(TSS_CONTEXT *tssContext,
554 					 TPMI_SH_AUTH_SESSION sessionHandle);
555 static TPM_RC TSS_HmacSession_GetSlotForHandle(TSS_CONTEXT *tssContext,
556 					       size_t *slotIndex,
557 					       TPMI_SH_AUTH_SESSION sessionHandle);
558 #endif
559 static TPM_RC TSS_HmacSession_Marshal(struct TSS_HMAC_CONTEXT *source,
560 				      uint16_t *written, uint8_t **buffer, uint32_t *size);
561 static TPM_RC TSS_HmacSession_Unmarshal(struct TSS_HMAC_CONTEXT *target,
562 					uint8_t **buffer, uint32_t *size);
563 
564 static TPM_RC TSS_Name_GetAllNames(TSS_CONTEXT *tssContext,
565 				   TPM2B_NAME **names);
566 static TPM_RC TSS_Name_GetName(TSS_CONTEXT *tssContext,
567 			       TPM2B_NAME *name,
568 			       TPM_HANDLE  handle);
569 static TPM_RC TSS_Name_Store(TSS_CONTEXT *tssContext,
570 			     TPM2B_NAME *name,
571 			     TPM_HANDLE handle,
572 			     const char *string);
573 static TPM_RC TSS_Name_Load(TSS_CONTEXT *tssContext,
574 			    TPM2B_NAME *name,
575 			    TPM_HANDLE handle,
576 			    const char *string);
577 static TPM_RC TSS_Name_Copy(TSS_CONTEXT *tssContext,
578 			    TPM_HANDLE outHandle,
579 			    const char *outString,
580 			    TPM_HANDLE inHandle,
581 			    const char *inString);
582 static TPM_RC TSS_Public_Store(TSS_CONTEXT *tssContext,
583 			       TPM2B_PUBLIC *public,
584 			       TPM_HANDLE handle,
585 			       const char *string);
586 static TPM_RC TSS_Public_Load(TSS_CONTEXT *tssContext,
587 			      TPM2B_PUBLIC *public,
588 			      TPM_HANDLE handle,
589 			      const char *string);
590 static TPM_RC TSS_Public_Copy(TSS_CONTEXT *tssContext,
591 			      TPM_HANDLE outHandle,
592 			      const char *outString,
593 			      TPM_HANDLE inHandle,
594 			      const char *inString);
595 #ifdef TPM_TSS_NOFILE
596 static TPM_RC TSS_ObjectPublic_GetSlotForHandle(TSS_CONTEXT *tssContext,
597 						size_t *slotIndex,
598 						TPM_HANDLE handle);
599 static TPM_RC TSS_ObjectPublic_DeleteData(TSS_CONTEXT *tssContext, TPM_HANDLE handle);
600 #endif
601 static TPM_RC TSS_DeleteHandle(TSS_CONTEXT *tssContext,
602 			       TPM_HANDLE handle);
603 #ifndef TPM_TSS_NOCRYPTO
604 static TPM_RC TSS_ObjectPublic_GetName(TPM2B_NAME *name,
605 				       TPMT_PUBLIC *tpmtPublic);
606 
607 static TPM_RC TSS_NVPublic_Store(TSS_CONTEXT *tssContext,
608 				 TPMS_NV_PUBLIC *nvPublic,
609 				 TPMI_RH_NV_INDEX handle);
610 static TPM_RC TSS_NVPublic_Load(TSS_CONTEXT *tssContext,
611 				TPMS_NV_PUBLIC *nvPublic,
612 				TPMI_RH_NV_INDEX handle);
613 #endif
614 static TPM_RC TSS_NVPublic_Delete(TSS_CONTEXT *tssContext,
615 				  TPMI_RH_NV_INDEX nvIndex);
616 #ifdef TPM_TSS_NOFILE
617 static TPM_RC TSS_NvPublic_GetSlotForHandle(TSS_CONTEXT *tssContext,
618 					    size_t *slotIndex,
619 					    TPMI_RH_NV_INDEX nvIndex);
620 #endif
621 
622 static TPM_RC TSS_Command_Decrypt(TSS_AUTH_CONTEXT *tssAuthContext,
623 				  struct TSS_HMAC_CONTEXT *session[],
624 				  TPMI_SH_AUTH_SESSION sessionHandle[],
625 				  unsigned int sessionAttributes[]);
626 #ifndef TPM_TSS_NOCRYPTO
627 static TPM_RC TSS_Command_DecryptXor(TSS_AUTH_CONTEXT *tssAuthContext,
628 				     struct TSS_HMAC_CONTEXT *session);
629 static TPM_RC TSS_Command_DecryptAes(TSS_AUTH_CONTEXT *tssAuthContext,
630 				     struct TSS_HMAC_CONTEXT *session);
631 
632 #endif	/* TPM_TSS_NOCRYPTO */
633 static TPM_RC TSS_Response_Encrypt(TSS_AUTH_CONTEXT *tssAuthContext,
634 				   struct TSS_HMAC_CONTEXT *session[],
635 				   TPMI_SH_AUTH_SESSION sessionHandle[],
636 				   unsigned int sessionAttributes[]);
637 #ifndef TPM_TSS_NOCRYPTO
638 static TPM_RC TSS_Response_EncryptXor(TSS_AUTH_CONTEXT *tssAuthContext,
639 				      struct TSS_HMAC_CONTEXT *session);
640 static TPM_RC TSS_Response_EncryptAes(TSS_AUTH_CONTEXT *tssAuthContext,
641 				      struct TSS_HMAC_CONTEXT *session);
642 
643 static TPM_RC TSS_Command_ChangeAuthProcessor(TSS_CONTEXT *tssContext,
644 					      struct TSS_HMAC_CONTEXT *session,
645 					      size_t handleNumber,
646 					      COMMAND_PARAMETERS *in);
647 #endif	/* TPM_TSS_NOCRYPTO */
648 
649 static TPM_RC TSS_Command_PreProcessor(TSS_CONTEXT *tssContext,
650 				       TPM_CC commandCode,
651 				       COMMAND_PARAMETERS *in,
652 				       EXTRA_PARAMETERS *extra);
653 static TPM_RC TSS_Response_PostProcessor(TSS_CONTEXT *tssContext,
654 					 COMMAND_PARAMETERS *in,
655 					 RESPONSE_PARAMETERS *out,
656 					 EXTRA_PARAMETERS *extra);
657 
658 static TPM_RC TSS_Sessions_GetDecryptSession(unsigned int *isDecrypt,
659 					     unsigned int *decryptSession,
660 					     TPMI_SH_AUTH_SESSION sessionHandle[],
661 					     unsigned int sessionAttributes[]);
662 static TPM_RC TSS_Sessions_GetEncryptSession(unsigned int *isEncrypt,
663 					     unsigned int *encryptSession,
664 					     TPMI_SH_AUTH_SESSION sessionHandle[],
665 					     unsigned int sessionAttributes[]);
666 
667 #ifndef TPM_TSS_NOFILE
668 static TPM_RC TSS_HashToString(char *str, uint8_t *digest);
669 #endif
670 #ifndef TPM_TSS_NOCRYPTO
671 #ifndef TPM_TSS_NORSA
672 static TPM_RC TSS_RSA_Salt(TPM2B_DIGEST 		*salt,
673 			   TPM2B_ENCRYPTED_SECRET	*encryptedSalt,
674 			   TPMT_PUBLIC			*publicArea);
675 #endif /* TPM_TSS_NORSA */
676 #endif /* TPM_TSS_NOCRYPTO */
677 extern int tssVerbose;
678 extern int tssVverbose;
679 extern int tssFirstCall;
680 
681 
TSS_Execute20(TSS_CONTEXT * tssContext,RESPONSE_PARAMETERS * out,COMMAND_PARAMETERS * in,EXTRA_PARAMETERS * extra,TPM_CC commandCode,va_list ap)682 TPM_RC TSS_Execute20(TSS_CONTEXT *tssContext,
683 		     RESPONSE_PARAMETERS *out,
684 		     COMMAND_PARAMETERS *in,
685 		     EXTRA_PARAMETERS *extra,
686 		     TPM_CC commandCode,
687 		     va_list ap)
688 {
689     TPM_RC		rc = 0;
690 
691     /* create a TSS authorization context */
692     if (rc == 0) {
693 	TSS_InitAuthContext(tssContext->tssAuthContext);
694     }
695     /* handle any command specific command pre-processing */
696     if (rc == 0) {
697 	rc = TSS_Command_PreProcessor(tssContext,
698 				      commandCode,
699 				      in,
700 				      extra);
701     }
702     /* marshal input parameters */
703     if (rc == 0) {
704 	if (tssVverbose) printf("TSS_Execute20: Command %08x marshal\n", commandCode);
705 	rc = TSS_Marshal(tssContext->tssAuthContext,
706 			 in,
707 			 commandCode);
708     }
709     /* execute the command */
710     if (rc == 0) {
711 	rc = TSS_Execute_valist(tssContext, in, ap);
712     }
713     /* unmarshal the response parameters */
714     if (rc == 0) {
715 	if (tssVverbose) printf("TSS_Execute20: Command %08x unmarshal\n", commandCode);
716 	rc = TSS_Unmarshal(tssContext->tssAuthContext, out);
717     }
718     /* handle any command specific response post-processing */
719     if (rc == 0) {
720 	if (tssVverbose) printf("TSS_Execute20: Command %08x post processor\n", commandCode);
721 	rc = TSS_Response_PostProcessor(tssContext,
722 					in,
723 					out,
724 					extra);
725     }
726     return rc;
727 }
728 
729 /* TSS_Execute_valist() transmits the marshaled command and receives the marshaled response.
730 
731    varargs are TPMI_SH_AUTH_SESSION sessionHandle, const char *password, unsigned int
732    sessionAttributes
733 
734    Terminates with sessionHandle TPM_RH_NULL
735 
736    Processes up to MAX_SESSION_NUM sessions.  It handles HMAC generation and command and response
737    parameter encryption.  It loads each session context, rolls nonces, and saves or deletes the
738    session context.
739 */
740 
TSS_Execute_valist(TSS_CONTEXT * tssContext,COMMAND_PARAMETERS * in,va_list ap)741 static TPM_RC TSS_Execute_valist(TSS_CONTEXT *tssContext,
742 				 COMMAND_PARAMETERS *in,
743 				 va_list ap)
744 {
745     TPM_RC		rc = 0;
746     int 		done;
747     int 		haveNames = FALSE;	/* names are common to all HMAC sessions */
748     size_t		i = 0;
749 
750     /* the vararg parameters */
751     TPMI_SH_AUTH_SESSION sessionHandle[MAX_SESSION_NUM];
752     const char 		*password[MAX_SESSION_NUM];
753     unsigned int	sessionAttributes[MAX_SESSION_NUM];
754 
755     /* structures filled in */
756     TPMS_AUTH_COMMAND 	*authCommand[MAX_SESSION_NUM];
757     TPMS_AUTH_RESPONSE 	*authResponse[MAX_SESSION_NUM];
758 
759     /* pointer to the above structures as used */
760     TPMS_AUTH_COMMAND 	*authC[MAX_SESSION_NUM];
761     TPMS_AUTH_RESPONSE 	*authR[MAX_SESSION_NUM];
762 
763     /* TSS sessions */
764     struct TSS_HMAC_CONTEXT *session[MAX_SESSION_NUM];
765     TPM2B_NAME *names[MAX_SESSION_NUM];
766 
767 
768     for (i = 0 ; i < MAX_SESSION_NUM ; i++) {
769 	authCommand[i] = NULL;		/* for safe free */
770 	authResponse[i] = NULL;		/* for safe free */
771  	names[i] = NULL;		/* for safe free */
772 	authC[i] = NULL;		/* array of TPMS_AUTH_COMMAND structures, NULL for
773 					   TSS_SetCmdAuths */
774 	authR[i] = NULL;		/* array of TPMS_AUTH_RESPONSE structures, NULL for
775 					   TSS_GetRspAuths */
776 	session[i] = NULL;		/* for free, used for HMAC and encrypt/decrypt sessions */
777 	/* the varargs list inputs */
778 	sessionHandle[i] = TPM_RH_NULL;
779 	password[i] = NULL;
780 	sessionAttributes[i] = 0;
781     }
782     /* Step 1: initialization */
783     if (tssVverbose) printf("TSS_Execute_valist: Step 1: initialization\n");
784     for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) ; i++) {
785 	if (rc == 0) {
786 	    rc = TSS_Malloc((unsigned char **)&authCommand[i],	/* freed @1 */
787 			    sizeof(TPMS_AUTH_COMMAND));
788 	}
789 	if (rc == 0) {
790 	    rc = TSS_Malloc((unsigned char **)&authResponse[i],	/* freed @2 */
791 			    sizeof(TPMS_AUTH_RESPONSE));
792 	}
793 	if (rc == 0) {
794 	    rc = TSS_Malloc((unsigned char **)&names[i],	/* freed @3 */
795 			    sizeof(TPM2B_NAME));
796 	}
797 	if (rc == 0) {
798 	    names[i]->b.size = 0;	/* to ignore unused names in cpHash calculation */
799 	}
800     }
801     /* Step 2: gather the command authorizations
802 
803        Process PWAP immediately
804        For HMAC, get the session context
805     */
806     done = FALSE;
807     for (i = 0 ; (rc == 0) && !done && (i < MAX_SESSION_NUM) ; i++) {
808  	sessionHandle[i] = va_arg(ap, TPMI_SH_AUTH_SESSION);	/* first vararg is the session
809 								   handle */
810 	password[i]= va_arg(ap, const char *);			/* second vararg is the password */
811 	sessionAttributes[i] = va_arg(ap, unsigned int);	/* third argument is
812 								   sessionAttributes */
813 	sessionAttributes[i] &= 0xff;				/* is uint8_t */
814 
815 	if (sessionHandle[i] != TPM_RH_NULL) {			/* varargs termination value */
816 
817 	    if (tssVverbose) printf("TSS_Execute_valist: Step 2: authorization %u\n",
818 				    (unsigned int)i);
819 	    if (tssVverbose) printf("TSS_Execute_valist: session %u handle %08x\n",
820 				    (unsigned int)i, sessionHandle[i]);
821 	    /* make used, non-NULL for command and response varargs */
822 	    authC[i] = authCommand[i];
823 	    authR[i] = authResponse[i];
824 
825 	    /* if password session, populate authC with password, etc. immediately */
826 	    if (sessionHandle[i] == TPM_RS_PW) {
827 		rc = TSS_PwapSession_Set(authC[i], password[i]);
828 	    }
829 	    /* if HMAC or encrypt/decrypt session  */
830 	    else {
831 		/* initialize a TSS HMAC session */
832 		if (rc == 0) {
833 		    rc = TSS_HmacSession_GetContext(&session[i]);
834 		}
835 		/* load the session created by startauthsession */
836 		if (rc == 0) {
837 		    rc = TSS_HmacSession_LoadSession(tssContext, session[i], sessionHandle[i]);
838 		}
839 		/* if there is at least one HMAC session, get the names corresponding to the
840 		   handles */
841 		if ((session[i]->sessionType == TPM_SE_HMAC) ||		/* HMAC session. OR */
842 		    ((session[i]->sessionType == TPM_SE_POLICY) &&	/* Policy session AND */
843 
844 #ifndef TPM_TSS_NOCRYPTO
845 		     ((session[i]->isAuthValueNeeded) || 		/* PolicyAuthValue ran, OR */
846 		      (session[i]->sessionKey.b.size != 0)))		/* Already session key (bind or salt) */
847 #else
848 		    (session[i]->isAuthValueNeeded))		/* PolicyAuthValue ran, OR */
849 #endif	/* TPM_TSS_NOCRYPTO */
850 		    ) {
851 		    if ((rc == 0) && !haveNames) {
852 			rc = TSS_Name_GetAllNames(tssContext, names);
853 			haveNames = TRUE;	/* get only once, minor optimization */
854 		    }
855 		}
856 	    }
857 	}
858 	else {
859 	    done = TRUE;
860 	}
861     }
862     /* Step 3: Roll nonceCaller, save in the session context for the response */
863     for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
864 	if (sessionHandle[i] != TPM_RS_PW) {		/* no nonce for password sessions */
865 	    if (tssVverbose)
866 		printf("TSS_Execute_valist: Step 3: nonceCaller %08x\n", sessionHandle[i]);
867 #ifndef TPM_TSS_NOCRYPTO
868 	    rc = TSS_HmacSession_SetNonceCaller(session[i], authC[i]);
869 #else
870 	    authC[i]->nonce.b.size = 16;
871 	    memset(&authC[i]->nonce.b.buffer, 0, 16);
872 #endif	/* TPM_TSS_NOCRYPTO */
873 	}
874     }
875 
876 #ifndef TPM_TSS_NOCRYPTO
877     /* Step 4: Calculate the HMAC key */
878     for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
879 	if (sessionHandle[i] != TPM_RS_PW) {		/* no HMAC key for password sessions */
880 	    if (tssVverbose) printf("TSS_Execute_valist: Step 4: Session %u HMAC key for %08x\n",
881 				    (unsigned int)i, sessionHandle[i]);
882 	    rc = TSS_HmacSession_SetHmacKey(tssContext, session[i], i, password[i]);
883 	}
884     }
885 #endif	/* TPM_TSS_NOCRYPTO */
886     /* Step 5: command parameter encryption */
887     if (rc == 0) {
888 	if (tssVverbose) printf("TSS_Execute_valist: Step 5: command encrypt\n");
889 	rc = TSS_Command_Decrypt(tssContext->tssAuthContext,
890 				 session,
891 				 sessionHandle,
892 				 sessionAttributes);
893     }
894     /* Step 6: for each HMAC session, calculate cpHash, calculate the HMAC, and set it in
895        TPMS_AUTH_COMMAND */
896     if (rc == 0) {
897 	if (tssVverbose) printf("TSS_Execute_valist: Step 6 calculate HMACs\n");
898 	rc = TSS_HmacSession_SetHMAC(tssContext->tssAuthContext,	/* TSS auth context */
899 				     session,		/* TSS session contexts */
900 				     authC,		/* output: command authorizations */
901 				     sessionHandle,	/* list of session handles for the command */
902 				     sessionAttributes, /* attributes for this command */
903 				     password,		/* for plaintext password sessions */
904 				     names[0],		/* Name */
905 				     names[1],		/* Name */
906 				     names[2]);		/* Name */
907     }
908     /* Step 7: set the command authorizations in the TSS command stream */
909     if (rc == 0) {
910 	if (tssVverbose) printf("TSS_Execute_valist: Step 7 set command authorizations\n");
911 	rc = TSS_SetCmdAuths(tssContext->tssAuthContext,
912 			     authC[0],
913 			     authC[1],
914 			     authC[2],
915 			     NULL);
916     }
917     /* Step 8: process the command.  Normally returns the TPM response code. */
918     if (rc == 0) {
919 	if (tssVverbose) printf("TSS_Execute_valist: Step 8: process the command\n");
920 	rc = TSS_AuthExecute(tssContext);
921     }
922     /* Step 9: get the response authorizations from the TSS response stream */
923     if (rc == 0) {
924 	if (tssVverbose) printf("TSS_Execute_valist: Step 9 get response authorizations\n");
925 	rc = TSS_GetRspAuths(tssContext->tssAuthContext,
926 			     authR[0],
927 			     authR[1],
928 			     authR[2],
929 			     NULL);
930     }
931     /* Step 10: process the response authorizations, validate the HMAC */
932     for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
933 	if (tssVverbose)
934 	    printf("TSS_Execute_valist: Step 10: process response authorization %08x\n",
935 		   sessionHandle[i]);
936 	if (sessionHandle[i] == TPM_RS_PW) {
937 	    rc = TSS_PwapSession_Verify(authR[i]);
938 	}
939 	/* HMAC session */
940 	else {
941 #ifndef TPM_TSS_NOCRYPTO
942 	    /* save nonceTPM in the session context */
943 	    if (rc == 0) {
944 		rc = TSS_TPM2B_Copy(&session[i]->nonceTPM.b, &authR[i]->nonce.b, sizeof(TPMU_HA));
945 	    }
946 #endif	/* TPM_TSS_NOCRYPTO */
947 	    /* the HMAC key is already part of the TSS session context.  For policy sessions with
948 	       policy password, the response hmac is empty. */
949 	    if ((session[i]->sessionType == TPM_SE_HMAC) ||
950 		((session[i]->sessionType == TPM_SE_POLICY) && (session[i]->isAuthValueNeeded))) {
951 #ifndef TPM_TSS_NOCRYPTO
952 		if (rc == 0) {
953 		    rc = TSS_Command_ChangeAuthProcessor(tssContext, session[i], i, in);
954 		}
955 		if (rc == 0) {
956 		    rc = TSS_HmacSession_Verify(tssContext->tssAuthContext, /* authorization
957 									       context */
958 						session[i],	/* TSS session context */
959 						authR[i]);	/* input: response authorization */
960 		}
961 #else
962 		in = in;
963 		if (tssVerbose)
964 		    printf("TSS_Execute_valist: "
965 			   "Error, HMAC verify with no crypto not implemented\n");
966 		rc = TSS_RC_NOT_IMPLEMENTED;
967 #endif	/* TPM_TSS_NOCRYPTO */
968 	    }
969 	}
970     }
971     /* Step 11: process the audit flag */
972     for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
973 	if ((sessionHandle[i] != TPM_RS_PW) &&
974 	    (session[i]->bind != TPM_RH_NULL) &&
975 	    (authR[i]->sessionAttributes.val & TPMA_SESSION_AUDIT)) {
976 	    if (tssVverbose) printf("TSS_Execute_valist: Step 11: process bind audit flag %08x\n",
977 				    sessionHandle[i]);
978 	    /* if bind audit session, bind value is lost and further use requires authValue */
979 	    session[i]->bind = TPM_RH_NULL;
980 	}
981     }
982     /* Step 12: process the response continue flag */
983     for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
984 	if (sessionHandle[i] != TPM_RS_PW) {
985 	    if (tssVverbose) printf("TSS_Execute_valist: Step 12: process continue flag %08x\n",
986 				    sessionHandle[i]);
987 	    rc = TSS_HmacSession_Continue(tssContext, session[i], authR[i]);
988 	}
989     }
990     /* Step 13: response parameter decryption */
991     if (rc == 0) {
992 	if (tssVverbose) printf("TSS_Execute_valist: Step 13: response decryption\n");
993 	rc = TSS_Response_Encrypt(tssContext->tssAuthContext,
994 				  session,
995 				  sessionHandle,
996 				  sessionAttributes);
997     }
998     /* cleanup */
999     for (i = 0 ; i < MAX_SESSION_NUM ; i++) {
1000 	TSS_HmacSession_FreeContext(session[i]);
1001 	free(authCommand[i]);		/* @1 */
1002  	free(authResponse[i]);		/* @2 */
1003 	free(names[i]);			/* @3 */
1004     }
1005     return rc;
1006 }
1007 
1008 /*
1009   PWAP - Password Session
1010 */
1011 
1012 /* TSS_PwapSession_Set() sets all members of the TPMS_AUTH_COMMAND structure for a PWAP session.
1013  */
1014 
TSS_PwapSession_Set(TPMS_AUTH_COMMAND * authCommand,const char * password)1015 static TPM_RC TSS_PwapSession_Set(TPMS_AUTH_COMMAND *authCommand,
1016 				  const char *password)
1017 {
1018     TPM_RC		rc = 0;
1019 
1020     if (rc == 0) {
1021 	authCommand->sessionHandle = TPM_RS_PW;
1022 	authCommand->nonce.t.size = 0;
1023 	authCommand->sessionAttributes.val = 0;
1024     }
1025     if (password != NULL) {
1026 	rc = TSS_TPM2B_StringCopy(&authCommand->hmac.b,
1027 				  password, sizeof(authCommand->hmac.t.buffer));
1028     }
1029     else {
1030 	authCommand->hmac.t.size = 0;
1031     }
1032     return rc;
1033 }
1034 
1035 /* TSS_PwapSession_Verify() verifies the PWAP session response. */
1036 
TSS_PwapSession_Verify(TPMS_AUTH_RESPONSE * authResponse)1037 static TPM_RC TSS_PwapSession_Verify(TPMS_AUTH_RESPONSE *authResponse)
1038 {
1039     TPM_RC		rc = 0;
1040 
1041     if (rc == 0) {
1042 	if (authResponse->nonce.t.size != 0) {
1043 	    if (tssVerbose) printf("TSS_PwapSession_Verify: nonce size %u not zero\n",
1044 				   authResponse->nonce.t.size);
1045 	    rc = TSS_RC_BAD_PWAP_NONCE;
1046 	}
1047     }
1048     if (rc == 0) {
1049 	if (authResponse->sessionAttributes.val != TPMA_SESSION_CONTINUESESSION) {
1050 	    if (tssVerbose) printf("TSS_PwapSession_Verify: continue %02x not set\n",
1051 				   authResponse->sessionAttributes.val);
1052 	    rc = TSS_RC_BAD_PWAP_ATTRIBUTES;
1053 	}
1054     }
1055     if (rc == 0) {
1056 	if (authResponse->hmac.t.size != 0) {
1057 	    if (tssVerbose) printf("TSS_PwapSession_Verify: HMAC size %u not zero\n",
1058 				   authResponse->hmac.t.size);
1059 	    rc = TSS_RC_BAD_PWAP_HMAC;
1060 	}
1061     }
1062     return rc;
1063 }
1064 
1065 /*
1066   HMAC Session
1067 */
1068 
TSS_HmacSession_GetContext(struct TSS_HMAC_CONTEXT ** session)1069 static TPM_RC TSS_HmacSession_GetContext(struct TSS_HMAC_CONTEXT **session)
1070 {
1071     TPM_RC rc = 0;
1072 
1073     if (rc == 0) {
1074         rc = TSS_Malloc((uint8_t **)session, sizeof(TSS_HMAC_CONTEXT));
1075     }
1076     if (rc == 0) {
1077 	TSS_HmacSession_InitContext(*session);
1078     }
1079     return rc;
1080 }
1081 
TSS_HmacSession_InitContext(struct TSS_HMAC_CONTEXT * session)1082 static void TSS_HmacSession_InitContext(struct TSS_HMAC_CONTEXT *session)
1083 {
1084     session->sessionHandle = TPM_RH_NULL;
1085     session->authHashAlg = TPM_ALG_NULL;
1086 #ifndef TPM_TSS_NOCRYPTO
1087     session->sizeInBytes = 0;
1088 #endif
1089     session->symmetric.algorithm = TPM_ALG_NULL;
1090     session->bind = TPM_RH_NULL;
1091     session->bindName.b.size = 0;
1092     session->bindAuthValue.t.size = 0;
1093 #ifndef TPM_TSS_NOCRYPTO
1094     memset(session->nonceTPM.t.buffer, 0, sizeof(TPMU_HA));
1095     session->nonceTPM.b.size = 0;
1096     memset(session->nonceCaller.t.buffer, 0, sizeof(TPMU_HA));
1097     session->nonceCaller.b.size = 0;
1098     memset(session->sessionKey.t.buffer, 0, sizeof(TPMU_HA));
1099     session->sessionKey.b.size = 0;
1100 #endif
1101     session->sessionType = 0;
1102     session->isPasswordNeeded = FALSE;
1103     session->isAuthValueNeeded = FALSE;
1104     memset(session->hmacKey.t.buffer, 0, sizeof(TPMU_HA) + sizeof(TPMU_HA));
1105     session->hmacKey.b.size = 0;
1106 #ifndef TPM_TSS_NOCRYPTO
1107     memset(session->sessionValue.t.buffer, 0, sizeof(TPMU_HA) + sizeof(TPMU_HA));
1108     session->sessionValue.b.size = 0;
1109 #endif
1110 }
1111 
TSS_HmacSession_FreeContext(struct TSS_HMAC_CONTEXT * session)1112 void TSS_HmacSession_FreeContext(struct TSS_HMAC_CONTEXT *session)
1113 {
1114     if (session != NULL) {
1115 	TSS_HmacSession_InitContext(session);
1116 	free(session);
1117     }
1118     return;
1119 }
1120 
1121 /* TSS_HmacSession_SetSessionKey() is called by the StartAuthSession post processor to calculate and
1122    store the session key
1123 
1124    19.6.8	sessionKey Creation
1125 */
1126 
1127 #ifndef TPM_TSS_NOCRYPTO
1128 
TSS_HmacSession_SetSessionKey(TSS_CONTEXT * tssContext,struct TSS_HMAC_CONTEXT * session,TPM2B_DIGEST * salt,TPMI_DH_ENTITY bind,TPM2B_AUTH * bindAuthValue)1129 static TPM_RC TSS_HmacSession_SetSessionKey(TSS_CONTEXT *tssContext,
1130 					    struct TSS_HMAC_CONTEXT *session,
1131 					    TPM2B_DIGEST *salt,
1132 					    TPMI_DH_ENTITY bind,
1133 					    TPM2B_AUTH *bindAuthValue)
1134 {
1135     TPM_RC		rc = 0;
1136     TPM2B_KEY 		key;		/* HMAC key for the KDFa */
1137 
1138     if (rc == 0) {
1139 	/* save the bind handle, non-null indicates a bound session */
1140 	session->bind = bind;
1141 	/* if bind, save the bind Name in the session context.  The handle might change, but the
1142 	   name will not */
1143 	if ((rc == 0) && (bind != TPM_RH_NULL)) {
1144 	    rc = TSS_Name_GetName(tssContext, &session->bindName, bind);
1145 	}
1146     }
1147     if (rc == 0) {
1148         if ((bind != TPM_RH_NULL) ||
1149 	    (salt->b.size != 0)) {
1150 
1151 	    /* session key is bindAuthValue || salt */
1152 	    /* copy bindAuthValue.  This is set during the post processor to either the supplied
1153 	       bind password or Empty */
1154 	    if (rc == 0) {
1155 		rc = TSS_TPM2B_Copy(&key.b, &bindAuthValue->b, sizeof(TPMU_HA) + sizeof(TPMT_HA));
1156 	    }
1157 	    /* copy salt.  This is set during the postprocessor to either the salt from the
1158 	       preprocessor or empty. */
1159 	    if (rc == 0) {
1160 		rc = TSS_TPM2B_Append(&key.b, &salt->b, sizeof(TPMU_HA) + sizeof(TPMT_HA));
1161 	    }
1162 	    if (rc == 0) {
1163 		if (tssVverbose) TSS_PrintAll("TSS_HmacSession_SetSessionKey: KDFa HMAC key",
1164 					      key.b.buffer, key.b.size);
1165 	    }
1166 	    /* KDFa for the session key */
1167 	    if (rc == 0) {
1168 		rc = TSS_KDFA(session->sessionKey.b.buffer,
1169 			      session->authHashAlg,
1170 			      &key.b,
1171 			      "ATH",
1172 			      &session->nonceTPM.b,
1173 			      &session->nonceCaller.b,
1174 			      session->sizeInBytes * 8);
1175 	    }
1176 	    if (rc == 0) {
1177 		session->sessionKey.b.size = session->sizeInBytes;
1178 		if (tssVverbose)
1179 		    TSS_PrintAll("TSS_HmacSession_SetSessionKey: Session key",
1180 				 session->sessionKey.b.buffer, session->sessionKey.b.size);
1181 	    }
1182 	}
1183 	else {
1184 	    session->sessionKey.b.size = 0;
1185 	}
1186     }
1187     return rc;
1188 }
1189 
1190 #endif	/* TPM_TSS_NOCRYPTO */
1191 
1192 /* TSS_HmacSession_SaveSession() saves a session in two cases:
1193 
1194    The initial session from startauthsession
1195    The updated session a TPM response
1196 */
1197 
1198 
TSS_HmacSession_SaveSession(TSS_CONTEXT * tssContext,struct TSS_HMAC_CONTEXT * session)1199 static TPM_RC TSS_HmacSession_SaveSession(TSS_CONTEXT *tssContext,
1200 					  struct TSS_HMAC_CONTEXT *session)
1201 {
1202     TPM_RC	rc = 0;
1203     uint8_t 	*buffer = NULL;		/* marshaled TSS_HMAC_CONTEXT */
1204     uint16_t	written = 0;
1205 #ifndef TPM_TSS_NOFILE
1206     char	sessionFilename[TPM_DATA_DIR_PATH_LENGTH];
1207     uint8_t *outBuffer = NULL;
1208     uint32_t outLength;
1209 #endif
1210 
1211     if (tssVverbose) printf("TSS_HmacSession_SaveSession: handle %08x\n", session->sessionHandle);
1212     if (rc == 0) {
1213 	rc = TSS_Structure_Marshal(&buffer,	/* freed @1 */
1214 				   &written,
1215 				   session,
1216 				   (MarshalFunction_t)TSS_HmacSession_Marshal);
1217     }
1218 #ifndef TPM_TSS_NOFILE
1219     if (rc == 0) {
1220 #ifndef TPM_TSS_NOCRYPTO
1221 	/* if the flag is set, encrypt the session state before store */
1222 	if (tssContext->tssEncryptSessions) {
1223 	    rc = TSS_AES_Encrypt(tssContext->tssSessionEncKey,
1224 				 &outBuffer,   	/* output, freed @2 */
1225 				 &outLength,	/* output */
1226 				 buffer,	/* input */
1227 				 written);	/* input */
1228 	}
1229 	/* else store the session state in plaintext */
1230 	else {
1231 #endif	/* TPM_TSS_NOCRYPTO */
1232 	    outBuffer = buffer;
1233 	    outLength = written;
1234 #ifndef TPM_TSS_NOCRYPTO
1235 	}
1236 #endif	/* TPM_TSS_NOCRYPTO */
1237     }
1238     /* save the session in a hard coded file name hxxxxxxxx.bin where xxxxxxxx is the session
1239        handle */
1240     if (rc == 0) {
1241 	sprintf(sessionFilename, "%s/h%08x.bin",
1242 		tssContext->tssDataDirectory, session->sessionHandle);
1243     }
1244     if (rc == 0) {
1245 	rc = TSS_File_WriteBinaryFile(outBuffer,
1246 				      outLength,
1247 				      sessionFilename);
1248     }
1249     if (tssContext->tssEncryptSessions) {
1250 	free(outBuffer);	/* @2 */
1251     }
1252 #else		/* no file support, save to context */
1253     if (rc == 0) {
1254 	rc = TSS_HmacSession_SaveData(tssContext,
1255 				      session->sessionHandle,
1256 				      written, buffer);
1257     }
1258 #endif
1259     free(buffer);	/* @1 */
1260     return rc;
1261 }
1262 
1263 /* TSS_HmacSession_LoadSession() loads an existing HMAC session context saved by:
1264 
1265    startauthsession
1266    an update after a TPM response
1267 */
1268 
TSS_HmacSession_LoadSession(TSS_CONTEXT * tssContext,struct TSS_HMAC_CONTEXT * session,TPMI_SH_AUTH_SESSION sessionHandle)1269 static TPM_RC TSS_HmacSession_LoadSession(TSS_CONTEXT *tssContext,
1270 					  struct TSS_HMAC_CONTEXT *session,
1271 					  TPMI_SH_AUTH_SESSION	sessionHandle)
1272 {
1273     TPM_RC		rc = 0;
1274     uint8_t 		*buffer = NULL;
1275     uint8_t 		*buffer1 = NULL;
1276 #ifndef TPM_TSS_NOFILE
1277     size_t 		length = 0;
1278     char		sessionFilename[TPM_DATA_DIR_PATH_LENGTH];
1279 #endif
1280     unsigned char 	*inData = NULL;		/* output */
1281     uint32_t 		inLength;		/* output */
1282 
1283     if (tssVverbose) printf("TSS_HmacSession_LoadSession: handle %08x\n", sessionHandle);
1284 #ifndef TPM_TSS_NOFILE
1285     /* load the session from a hard coded file name hxxxxxxxx.bin where xxxxxxxx is the session
1286        handle */
1287     if (rc == 0) {
1288 	sprintf(sessionFilename, "%s/h%08x.bin", tssContext->tssDataDirectory, sessionHandle);
1289 	rc = TSS_File_ReadBinaryFile(&buffer,     /* freed @1 */
1290 				     &length,
1291 				     sessionFilename);
1292     }
1293     if (rc == 0) {
1294 #ifndef TPM_TSS_NOCRYPTO
1295 	/* if the flag is set, decrypt the session state before unmarshal */
1296 	if (tssContext->tssEncryptSessions) {
1297 	    rc = TSS_AES_Decrypt(tssContext->tssSessionDecKey,
1298 				 &inData,   	/* output, freed @2 */
1299 				 &inLength,	/* output */
1300 				 buffer,	/* input */
1301 				 length);	/* input */
1302 	}
1303 	/* else the session was loaded in plaintext */
1304 	else {
1305 #endif	/* TPM_TSS_NOCRYPTO */
1306 	    inData = buffer;
1307 	    inLength = length;
1308 #ifndef TPM_TSS_NOCRYPTO
1309 	}
1310 #endif	/* TPM_TSS_NOCRYPTO */
1311     }
1312 #else		/* no file support, load from context */
1313     if (rc == 0) {
1314 	rc = TSS_HmacSession_LoadData(tssContext,
1315 				      &inLength, &inData,
1316 				      sessionHandle);
1317     }
1318 #endif
1319     if (rc == 0) {
1320 	uint32_t ilength = inLength;
1321 	buffer1 = inData;
1322 	rc = TSS_HmacSession_Unmarshal(session, &buffer1, &ilength);
1323     }
1324 #ifndef TPM_TSS_NOFILE
1325     if (tssContext->tssEncryptSessions) {
1326 	free(inData);	/* @2 */
1327     }
1328 #endif
1329     free(buffer);	/* @1 */
1330     return rc;
1331 }
1332 
1333 #ifdef TPM_TSS_NOFILE
1334 
TSS_HmacSession_SaveData(TSS_CONTEXT * tssContext,TPMI_SH_AUTH_SESSION sessionHandle,uint32_t outLength,uint8_t * outBuffer)1335 static TPM_RC TSS_HmacSession_SaveData(TSS_CONTEXT *tssContext,
1336 				       TPMI_SH_AUTH_SESSION sessionHandle,
1337 				       uint32_t outLength,
1338 				       uint8_t *outBuffer)
1339 {
1340     TPM_RC	rc = 0;
1341     size_t	slotIndex;
1342 
1343     /* if this handle is already used, overwrite the slot */
1344     if (rc == 0) {
1345 	rc = TSS_HmacSession_GetSlotForHandle(tssContext, &slotIndex, sessionHandle);
1346 	if (rc != 0) {
1347 	    rc = TSS_HmacSession_GetSlotForHandle(tssContext, &slotIndex, TPM_RH_NULL);
1348 	    if (rc == 0) {
1349 		tssContext->sessions[slotIndex].sessionHandle = sessionHandle;
1350 	    }
1351 	    else {
1352 		if (tssVerbose)
1353 		    printf("TSS_HmacSession_SaveData: Error, no slot available for handle %08x\n",
1354 			   sessionHandle);
1355 	    }
1356 	}
1357     }
1358     /* reallocate memory and adjust the size */
1359     if (rc == 0) {
1360 	rc = TSS_Realloc(&tssContext->sessions[slotIndex].sessionData, outLength);
1361     }
1362     if (rc == 0) {
1363 	tssContext->sessions[slotIndex].sessionDataLength = outLength;
1364 	memcpy(tssContext->sessions[slotIndex].sessionData, outBuffer, outLength);
1365     }
1366     return rc;
1367 }
1368 
TSS_HmacSession_LoadData(TSS_CONTEXT * tssContext,uint32_t * inLength,uint8_t ** inData,TPMI_SH_AUTH_SESSION sessionHandle)1369 static TPM_RC TSS_HmacSession_LoadData(TSS_CONTEXT *tssContext,
1370 				       uint32_t *inLength, uint8_t **inData,
1371 				       TPMI_SH_AUTH_SESSION sessionHandle)
1372 {
1373     TPM_RC	rc = 0;
1374     size_t	slotIndex;
1375 
1376     if (rc == 0) {
1377 	rc = TSS_HmacSession_GetSlotForHandle(tssContext, &slotIndex, sessionHandle);
1378 	if (rc != 0) {
1379 	    if (tssVerbose)
1380 		printf("TSS_HmacSession_LoadData: Error, no slot found for handle %08x\n",
1381 		       sessionHandle);
1382 	}
1383     }
1384     if (rc == 0) {
1385 	*inLength = tssContext->sessions[slotIndex].sessionDataLength;
1386 	*inData = tssContext->sessions[slotIndex].sessionData;
1387     }
1388     return rc;
1389 }
1390 
TSS_HmacSession_DeleteData(TSS_CONTEXT * tssContext,TPMI_SH_AUTH_SESSION sessionHandle)1391 static TPM_RC TSS_HmacSession_DeleteData(TSS_CONTEXT *tssContext,
1392 					 TPMI_SH_AUTH_SESSION sessionHandle)
1393 {
1394     TPM_RC	rc = 0;
1395     size_t	slotIndex;
1396 
1397     if (rc == 0) {
1398 	rc = TSS_HmacSession_GetSlotForHandle(tssContext, &slotIndex, sessionHandle);
1399 	if (rc != 0) {
1400 	    if (tssVerbose)
1401 		printf("TSS_HmacSession_DeleteData: Error, no slot found for handle %08x\n",
1402 		       sessionHandle);
1403 	}
1404     }
1405     if (rc == 0) {
1406 	tssContext->sessions[slotIndex].sessionHandle = TPM_RH_NULL;
1407 	/* erase any secrets */
1408 	memset(tssContext->sessions[slotIndex].sessionData, 0,
1409 	       tssContext->sessions[slotIndex].sessionDataLength);
1410 	free(tssContext->sessions[slotIndex].sessionData);
1411 	tssContext->sessions[slotIndex].sessionData = NULL;
1412 	tssContext->sessions[slotIndex].sessionDataLength = 0;
1413     }
1414     return rc;
1415 }
1416 
1417 /* TSS_HmacSession_GetSlotForHandle() finds the session slot corresponding to the session handle.
1418 
1419    Returns non-zero if no slot is found.
1420 */
1421 
TSS_HmacSession_GetSlotForHandle(TSS_CONTEXT * tssContext,size_t * slotIndex,TPMI_SH_AUTH_SESSION sessionHandle)1422 static TPM_RC TSS_HmacSession_GetSlotForHandle(TSS_CONTEXT *tssContext,
1423 					       size_t *slotIndex,
1424 					       TPMI_SH_AUTH_SESSION sessionHandle)
1425 {
1426     size_t 	i;
1427 
1428     /* search all slots for handle */
1429     for (i = 0 ; i < (sizeof(tssContext->sessions) / sizeof(TSS_SESSIONS)) ; i++) {
1430 	if (tssContext->sessions[i].sessionHandle == sessionHandle) {
1431 	    *slotIndex = i;
1432 	    return 0;
1433 	}
1434     }
1435     return TSS_RC_NO_SESSION_SLOT;
1436 }
1437 
1438 #endif
1439 
TSS_HmacSession_Marshal(struct TSS_HMAC_CONTEXT * source,uint16_t * written,uint8_t ** buffer,uint32_t * size)1440 static TPM_RC TSS_HmacSession_Marshal(struct TSS_HMAC_CONTEXT *source,
1441 					uint16_t *written,
1442 					uint8_t **buffer,
1443 					uint32_t *size)
1444 {
1445     TPM_RC rc = 0;
1446 
1447     if (rc == 0) {
1448 	rc = TSS_TPMI_SH_AUTH_SESSION_Marshalu(&source->sessionHandle, written, buffer, size);
1449     }
1450     if (rc == 0) {
1451 	rc = TSS_TPMI_ALG_HASH_Marshalu(&source->authHashAlg, written, buffer, size);
1452     }
1453 #ifndef TPM_TSS_NOCRYPTO
1454     if (rc == 0) {
1455 	rc = TSS_UINT32_Marshalu(&source->sizeInBytes, written, buffer, size);
1456     }
1457 #endif
1458     if (rc == 0) {
1459 	rc = TSS_TPMT_SYM_DEF_Marshalu(&source->symmetric, written, buffer, size);
1460     }
1461     if (rc == 0) {
1462 	rc = TSS_TPMI_DH_ENTITY_Marshalu(&source->bind, written, buffer, size);
1463     }
1464     if (rc == 0) {
1465 	rc = TSS_TPM2B_NAME_Marshalu(&source->bindName, written, buffer, size);
1466     }
1467 #ifdef TPM_WINDOWS
1468     /* FIXME Why does a VS release build need a printf here? */
1469     if (tssVverbose) printf("");
1470 #endif
1471     if (rc == 0) {
1472 	rc = TSS_TPM2B_AUTH_Marshalu(&source->bindAuthValue, written, buffer, size);
1473     }
1474 #ifndef TPM_TSS_NOCRYPTO
1475     if (rc == 0) {
1476 	rc = TSS_TPM2B_NONCE_Marshalu(&source->nonceTPM, written, buffer, size);
1477     }
1478     if (rc == 0) {
1479 	rc = TSS_TPM2B_NONCE_Marshalu(&source->nonceCaller, written, buffer, size);
1480     }
1481     if (rc == 0) {
1482 	rc = TSS_TPM2B_DIGEST_Marshalu(&source->sessionKey, written, buffer, size);
1483     }
1484 #endif
1485     if (rc == 0) {
1486 	rc = TSS_TPM_SE_Marshalu(&source->sessionType, written, buffer, size);
1487     }
1488     if (rc == 0) {
1489 	rc = TSS_UINT8_Marshalu(&source->isPasswordNeeded, written, buffer, size);
1490     }
1491     if (rc == 0) {
1492 	rc = TSS_UINT8_Marshalu(&source->isAuthValueNeeded, written, buffer, size);
1493     }
1494     return rc;
1495 }
1496 
TSS_HmacSession_Unmarshal(struct TSS_HMAC_CONTEXT * target,uint8_t ** buffer,uint32_t * size)1497 static TPM_RC TSS_HmacSession_Unmarshal(struct TSS_HMAC_CONTEXT *target,
1498 					uint8_t **buffer, uint32_t *size)
1499 {
1500     TPM_RC rc = 0;
1501 
1502     if (rc == 0) {
1503 	rc = TSS_TPMI_SH_AUTH_SESSION_Unmarshalu(&target->sessionHandle, buffer, size, NO);
1504     }
1505     if (rc == 0) {
1506 	rc = TSS_TPMI_ALG_HASH_Unmarshalu(&target->authHashAlg, buffer, size, NO);
1507     }
1508 #ifndef TPM_TSS_NOCRYPTO
1509     if (rc == 0) {
1510 	rc = TSS_UINT32_Unmarshalu(&target->sizeInBytes, buffer, size);
1511     }
1512 #endif
1513     if (rc == 0) {
1514 	rc = TSS_TPMT_SYM_DEF_Unmarshalu(&target->symmetric, buffer, size, YES);
1515     }
1516     if (rc == 0) {
1517 	rc = TSS_TPMI_DH_ENTITY_Unmarshalu(&target->bind, buffer, size, YES);
1518     }
1519     if (rc == 0) {
1520 	rc = TSS_TPM2B_NAME_Unmarshalu(&target->bindName, buffer, size);
1521     }
1522     if (rc == 0) {
1523 	rc = TSS_TPM2B_AUTH_Unmarshalu(&target->bindAuthValue, buffer, size);
1524     }
1525 #ifndef TPM_TSS_NOCRYPTO
1526     if (rc == 0) {
1527 	rc = TSS_TPM2B_NONCE_Unmarshalu(&target->nonceTPM, buffer, size);
1528     }
1529     if (rc == 0) {
1530 	rc = TSS_TPM2B_NONCE_Unmarshalu(&target->nonceCaller, buffer, size);
1531     }
1532     if (rc == 0) {
1533 	rc = TSS_TPM2B_DIGEST_Unmarshalu(&target->sessionKey, buffer, size);
1534     }
1535 #endif
1536     if (rc == 0) {
1537 	rc = TSS_TPM_SE_Unmarshalu(&target->sessionType, buffer, size);
1538     }
1539     if (rc == 0) {
1540 	rc = TSS_UINT8_Unmarshalu(&target->isPasswordNeeded, buffer, size);
1541     }
1542     if (rc == 0) {
1543 	rc = TSS_UINT8_Unmarshalu(&target->isAuthValueNeeded, buffer, size);
1544     }
1545     return rc;
1546 }
1547 
1548 /*
1549   Name handling
1550 */
1551 
1552 /* TSS_Name_GetAllNames() files in the names array based on the handles marshaled into the TSS
1553    context command stream. */
1554 
TSS_Name_GetAllNames(TSS_CONTEXT * tssContext,TPM2B_NAME ** names)1555 static TPM_RC TSS_Name_GetAllNames(TSS_CONTEXT *tssContext,
1556 				   TPM2B_NAME **names)
1557 {
1558     TPM_RC	rc = 0;
1559     size_t	i;
1560     size_t	commandHandleCount;	/* number of handles in the command stream */
1561     TPM_HANDLE  commandHandle;
1562 
1563     /* get the number of handles in the command stream */
1564     if (rc == 0) {
1565 	rc = TSS_GetCommandHandleCount(tssContext->tssAuthContext, &commandHandleCount);
1566 	if (tssVverbose) printf("TSS_Name_GetAllNames: commandHandleCount %u\n",
1567 				(unsigned int)commandHandleCount);
1568     }
1569     for (i = 0 ; (rc == 0) && (i < commandHandleCount) ; i++) {
1570 	/* get a handle from the command stream */
1571 	if (rc == 0) {
1572 	    rc = TSS_GetCommandHandle(tssContext->tssAuthContext,
1573 				      &commandHandle,
1574 				      i);
1575 	}
1576 	/* get the Name corresponding to the handle */
1577 	if (rc == 0) {
1578 	    if (tssVverbose) printf("TSS_Name_GetAllNames: commandHandle %u %08x\n",
1579 				    (unsigned int)i, commandHandle);
1580 	    rc = TSS_Name_GetName(tssContext, names[i], commandHandle);
1581 	}
1582     }
1583     return rc;
1584 }
1585 
1586 /* TSS_Name_GetName() gets the Name associated with the handle */
1587 
TSS_Name_GetName(TSS_CONTEXT * tssContext,TPM2B_NAME * name,TPM_HANDLE handle)1588 static TPM_RC TSS_Name_GetName(TSS_CONTEXT *tssContext,
1589 			       TPM2B_NAME *name,
1590 			       TPM_HANDLE  handle)
1591 {
1592     TPM_RC	rc = 0;
1593     TPM_HT 	handleType;
1594 
1595     if (tssVverbose) printf("TSS_Name_GetName: Handle %08x\n", handle);
1596     handleType = (TPM_HT) ((handle & HR_RANGE_MASK) >> HR_SHIFT);
1597 
1598     /* Table 3 - Equations for Computing Entity Names */
1599     switch (handleType) {
1600 	/* for these, the Name is simply the handle value */
1601       case TPM_HT_PCR:
1602       case TPM_HT_HMAC_SESSION:
1603       case TPM_HT_POLICY_SESSION:
1604       case TPM_HT_PERMANENT:
1605 	rc = TSS_TPM2B_CreateUint32(&name->b, handle, sizeof(name->t.name));
1606 	break;
1607 	/* for NV, the Names was calculated at NV read public */
1608       case TPM_HT_NV_INDEX:
1609 	/* for objects, the Name was returned at creation or load */
1610       case TPM_HT_TRANSIENT:
1611       case TPM_HT_PERSISTENT:
1612 	rc = TSS_Name_Load(tssContext, name, handle, NULL);
1613 	break;
1614       default:
1615 	if (tssVerbose) printf("TSS_Name_GetName: not implemented for handle %08x\n", handle);
1616 	rc = TSS_RC_NAME_NOT_IMPLEMENTED;
1617 	break;
1618     }
1619     if (rc == 0) {
1620 	if (tssVverbose)
1621 	    TSS_PrintAll("TSS_Name_GetName: ",
1622 			 name->t.name, name->t.size);
1623     }
1624 
1625     return rc;
1626 }
1627 
1628 /* TSS_Name_Store() stores the 'name' parameter in a file.
1629 
1630    If handle is not 0, the handle is used as the file name.
1631 
1632    If 'string' is not NULL, the string is used as the file name.
1633 */
1634 
1635 #ifndef TPM_TSS_NOFILE
1636 
TSS_Name_Store(TSS_CONTEXT * tssContext,TPM2B_NAME * name,TPM_HANDLE handle,const char * string)1637 static TPM_RC TSS_Name_Store(TSS_CONTEXT *tssContext,
1638 			     TPM2B_NAME *name,
1639 			     TPM_HANDLE handle,
1640 			     const char *string)
1641 {
1642     TPM_RC 	rc = 0;
1643     char 	nameFilename[TPM_DATA_DIR_PATH_LENGTH];
1644 
1645     if (rc == 0) {
1646 	if (string == NULL) {
1647 	    if (handle != 0) {
1648 		sprintf(nameFilename, "%s/h%08x.bin", tssContext->tssDataDirectory, handle);
1649 	    }
1650 	    else {
1651 		if (tssVerbose) printf("TSS_Name_Store: handle and string are both null");
1652 		rc = TSS_RC_NAME_FILENAME;
1653 	    }
1654 	}
1655 	else {
1656 	    if (handle == 0) {
1657 		sprintf(nameFilename, "%s/h%s.bin", tssContext->tssDataDirectory, string);
1658 	    }
1659 	    else {
1660 		if (tssVerbose) printf("TSS_Name_Store: handle and string are both not null");
1661 		rc = TSS_RC_NAME_FILENAME;
1662 	    }
1663 	}
1664     }
1665     if (rc == 0) {
1666 	if (tssVverbose) printf("TSS_Name_Store: File %s\n", nameFilename);
1667 	rc = TSS_File_WriteBinaryFile(name->b.buffer, name->b.size, nameFilename);
1668     }
1669     return rc;
1670 }
1671 
1672 #endif
1673 
1674 /* TSS_Name_Load() loads the 'name' from a file.
1675 
1676    If handle is not 0, the handle is used as the file name.
1677 
1678    If 'string' is not NULL, the string is used as the file name.
1679 */
1680 
1681 #ifndef TPM_TSS_NOFILE
1682 
TSS_Name_Load(TSS_CONTEXT * tssContext,TPM2B_NAME * name,TPM_HANDLE handle,const char * string)1683 static TPM_RC TSS_Name_Load(TSS_CONTEXT *tssContext,
1684 			    TPM2B_NAME *name,
1685 			    TPM_HANDLE handle,
1686 			    const char *string)
1687 {
1688     TPM_RC 		rc = 0;
1689     char 		nameFilename[TPM_DATA_DIR_PATH_LENGTH];
1690 
1691     if (rc == 0) {
1692 	if (string == NULL) {
1693 	    if (handle != 0) {
1694 		sprintf(nameFilename, "%s/h%08x.bin", tssContext->tssDataDirectory, handle);
1695 	    }
1696 	    else {
1697 		if (tssVerbose) printf("TSS_Name_Load: handle and string are both null\n");
1698 		rc = TSS_RC_NAME_FILENAME;
1699 	    }
1700 	}
1701 	else {
1702 	    if (handle == 0) {
1703 		sprintf(nameFilename, "%s/h%s.bin", tssContext->tssDataDirectory, string);
1704 	    }
1705 	    else {
1706 		if (tssVerbose) printf("TSS_Name_Load: handle and string are both not null\n");
1707 		rc = TSS_RC_NAME_FILENAME;
1708 	    }
1709 	}
1710     }
1711     if (rc == 0) {
1712 	if (tssVverbose) printf("TSS_Name_Load: File %s\n", nameFilename);
1713 	rc = TSS_File_Read2B(&name->b,
1714 			     sizeof(name->t.name),
1715 			     nameFilename);
1716     }
1717     return rc;
1718 }
1719 
1720 #endif
1721 
1722 /* TSS_Name_Store() stores the 'name' parameter the TSS context.
1723 
1724 */
1725 
1726 #ifdef TPM_TSS_NOFILE
1727 
TSS_Name_Store(TSS_CONTEXT * tssContext,TPM2B_NAME * name,TPM_HANDLE handle,const char * string)1728 static TPM_RC TSS_Name_Store(TSS_CONTEXT *tssContext,
1729 			     TPM2B_NAME *name,
1730 			     TPM_HANDLE handle,
1731 			     const char *string)
1732 {
1733     TPM_RC 	rc = 0;
1734     TPM_HT 	handleType;
1735     size_t	slotIndex;
1736 
1737     if (tssVverbose) printf("TSS_Name_Store: Handle %08x\n", handle);
1738     handleType = (TPM_HT) ((handle & HR_RANGE_MASK) >> HR_SHIFT);
1739 
1740     switch (handleType) {
1741       case TPM_HT_NV_INDEX:
1742 	/* for NV, the Name was returned at creation */
1743 	rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
1744 	if (rc != 0) {
1745 	    rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, TPM_RH_NULL);
1746 	    if (rc == 0) {
1747 		tssContext->nvPublic[slotIndex].nvIndex = handle;
1748 	    }
1749 	    else {
1750 		if (tssVerbose)
1751 		    printf("TSS_Name_Store: Error, no slot available for handle %08x\n", handle);
1752 	    }
1753 	}
1754 	if (rc == 0) {
1755 	    tssContext->nvPublic[slotIndex].name = *name;
1756 	}
1757 	break;
1758       case TPM_HT_TRANSIENT:
1759       case TPM_HT_PERSISTENT:
1760 	if (rc == 0) {
1761 	    if (string == NULL) {
1762 		if (handle != 0) {
1763 		    /* if this handle is already used, overwrite the slot */
1764 		    rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
1765 		    if (rc != 0) {
1766 			rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, TPM_RH_NULL);
1767 			if (rc == 0) {
1768 			    tssContext->objectPublic[slotIndex].objectHandle = handle;
1769 			}
1770 			else {
1771 			    if (tssVerbose)
1772 				printf("TSS_Name_Store: "
1773 				       "Error, no slot available for handle %08x\n",
1774 				       handle);
1775 			}
1776 		    }
1777 		}
1778 		else {
1779 		    if (tssVerbose) printf("TSS_Name_Store: handle and string are both null");
1780 		    rc = TSS_RC_NAME_FILENAME;
1781 		}
1782 	    }
1783 	    else {
1784 		if (handle == 0) {
1785 		    if (tssVerbose) printf("TSS_Name_Store: string unimplemented");
1786 		    rc = TSS_RC_NAME_FILENAME;
1787 		}
1788 		else {
1789 		    if (tssVerbose) printf("TSS_Name_Store: handle and string are both not null");
1790 		    rc = TSS_RC_NAME_FILENAME;
1791 		}
1792 	    }
1793 	}
1794 	if (rc == 0) {
1795 	    tssContext->objectPublic[slotIndex].name = *name;
1796 	}
1797 	break;
1798       default:
1799 	if (tssVerbose) printf("TSS_Name_Store: handle type %02x unimplemented", handleType);
1800 	rc = TSS_RC_NAME_FILENAME;
1801     }
1802     return rc;
1803 }
1804 
1805 #endif
1806 
1807 /* TSS_Name_Load() loads the 'name' from the TSS context.
1808 
1809 */
1810 
1811 #ifdef TPM_TSS_NOFILE
1812 
TSS_Name_Load(TSS_CONTEXT * tssContext,TPM2B_NAME * name,TPM_HANDLE handle,const char * string)1813 static TPM_RC TSS_Name_Load(TSS_CONTEXT *tssContext,
1814 			    TPM2B_NAME *name,
1815 			    TPM_HANDLE handle,
1816 			    const char *string)
1817 {
1818     TPM_RC 	rc = 0;
1819     TPM_HT 	handleType;
1820     size_t	slotIndex;
1821 
1822     string = string;
1823 
1824     if (tssVverbose) printf("TSS_Name_Load: Handle %08x\n", handle);
1825     handleType = (TPM_HT) ((handle & HR_RANGE_MASK) >> HR_SHIFT);
1826 
1827     switch (handleType) {
1828       case TPM_HT_NV_INDEX:
1829 	rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
1830 	if (rc != 0) {
1831 	    if (tssVerbose)
1832 		printf("TSS_Name_Load: Error, no slot found for handle %08x\n", handle);
1833 	}
1834 	if (rc == 0) {
1835 	    *name = tssContext->nvPublic[slotIndex].name;
1836 	}
1837 	break;
1838       case TPM_HT_TRANSIENT:
1839       case TPM_HT_PERSISTENT:
1840 	rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
1841 	if (rc != 0) {
1842 	    if (tssVerbose)
1843 		printf("TSS_Name_Load: Error, no slot found for handle %08x\n", handle);
1844 	}
1845 	if (rc == 0) {
1846 	    *name = tssContext->objectPublic[slotIndex].name;
1847 	}
1848 	break;
1849       default:
1850 	if (tssVerbose) printf("TSS_Name_Load: handle type %02x unimplemented", handleType);
1851 	rc = TSS_RC_NAME_FILENAME;
1852 
1853     }
1854     return rc;
1855 }
1856 
1857 #endif
1858 
1859 /* TSS_Name_Copy() copies the name from either inHandle or inString to either outHandle or
1860    outString */
1861 
TSS_Name_Copy(TSS_CONTEXT * tssContext,TPM_HANDLE outHandle,const char * outString,TPM_HANDLE inHandle,const char * inString)1862 static TPM_RC TSS_Name_Copy(TSS_CONTEXT *tssContext,
1863 			    TPM_HANDLE outHandle,
1864 			    const char *outString,
1865 			    TPM_HANDLE inHandle,
1866 			    const char *inString)
1867 {
1868     TPM_RC 		rc = 0;
1869     TPM2B_NAME 		name;
1870 
1871     if (rc == 0) {
1872 	rc = TSS_Name_Load(tssContext, &name, inHandle, inString);
1873     }
1874     if (rc == 0) {
1875 	rc = TSS_Name_Store(tssContext, &name, outHandle, outString);
1876     }
1877     return rc;
1878 }
1879 
1880 /* TSS_Public_Store() stores the 'public' parameter in a file.
1881 
1882    If handle is not 0, the handle is used as the file name.
1883 
1884    If 'string' is not NULL, the string is used as the file name.
1885 */
1886 
1887 #ifndef TPM_TSS_NOFILE
1888 
TSS_Public_Store(TSS_CONTEXT * tssContext,TPM2B_PUBLIC * public,TPM_HANDLE handle,const char * string)1889 static TPM_RC TSS_Public_Store(TSS_CONTEXT *tssContext,
1890 			       TPM2B_PUBLIC *public,
1891 			       TPM_HANDLE handle,
1892 			       const char *string)
1893 {
1894     TPM_RC 	rc = 0;
1895     char 	publicFilename[TPM_DATA_DIR_PATH_LENGTH];
1896 
1897     if (rc == 0) {
1898 	if (string == NULL) {
1899 	    if (handle != 0) {		/* store by handle */
1900 		sprintf(publicFilename, "%s/hp%08x.bin", tssContext->tssDataDirectory, handle);
1901 	    }
1902 	    else {
1903 		if (tssVerbose) printf("TSS_Public_Store: handle and string are both null");
1904 		rc = TSS_RC_NAME_FILENAME;
1905 	    }
1906 	}
1907 	else {
1908 	    if (handle == 0) {		/* store by string */
1909 		sprintf(publicFilename, "%s/hp%s.bin", tssContext->tssDataDirectory, string);
1910 	    }
1911 	    else {
1912 		if (tssVerbose) printf("TSS_Public_Store: handle and string are both not null");
1913 		rc = TSS_RC_NAME_FILENAME;
1914 	    }
1915 	}
1916     }
1917     if (rc == 0) {
1918 	if (tssVverbose) printf("TSS_Public_Store: File %s\n", publicFilename);
1919 	rc = TSS_File_WriteStructure(public,
1920 				     (MarshalFunction_t)TSS_TPM2B_PUBLIC_Marshalu,
1921 				     publicFilename);
1922     }
1923     return rc;
1924 }
1925 
1926 #endif
1927 
1928 /* TSS_Public_Load() loads the 'public' parameter from a file.
1929 
1930    If handle is not 0, the handle is used as the file name.
1931 
1932    If 'string' is not NULL, the string is used as the file name.
1933 */
1934 
1935 #ifndef TPM_TSS_NOFILE
1936 
TSS_Public_Load(TSS_CONTEXT * tssContext,TPM2B_PUBLIC * public,TPM_HANDLE handle,const char * string)1937 static TPM_RC TSS_Public_Load(TSS_CONTEXT *tssContext,
1938 			      TPM2B_PUBLIC *public,
1939 			      TPM_HANDLE handle,
1940 			      const char *string)
1941 {
1942     TPM_RC 	rc = 0;
1943     char 	publicFilename[TPM_DATA_DIR_PATH_LENGTH];
1944 
1945     if (rc == 0) {
1946 	if (string == NULL) {
1947 	    if (handle != 0) {
1948 		sprintf(publicFilename, "%s/hp%08x.bin", tssContext->tssDataDirectory, handle);
1949 	    }
1950 	    else {
1951 		if (tssVerbose) printf("TSS_Public_Load: handle and string are both null\n");
1952 		rc = TSS_RC_NAME_FILENAME;
1953 	    }
1954 	}
1955 	else {
1956 	    if (handle == 0) {
1957 		sprintf(publicFilename, "%s/hp%s.bin", tssContext->tssDataDirectory, string);
1958 	    }
1959 	    else {
1960 		if (tssVerbose) printf("TSS_Public_Load: handle and string are both not null\n");
1961 		rc = TSS_RC_NAME_FILENAME;
1962 	    }
1963 	}
1964     }
1965     if (rc == 0) {
1966 	if (tssVverbose) printf("TSS_Public_Load: File %s\n", publicFilename);
1967 	rc = TSS_File_ReadStructureFlag(public,
1968 					(UnmarshalFunctionFlag_t)TSS_TPM2B_PUBLIC_Unmarshalu,
1969 					TRUE,			/* NULL permitted */
1970 					publicFilename);
1971     }
1972     return rc;
1973 }
1974 
1975 #endif 	/* TPM_TSS_NOFILE */
1976 
1977 /* TSS_Public_Copy() copies the TPM2B_PUBLIC from either inHandle or inString to either outHandle or
1978    outString */
1979 
TSS_Public_Copy(TSS_CONTEXT * tssContext,TPM_HANDLE outHandle,const char * outString,TPM_HANDLE inHandle,const char * inString)1980 static TPM_RC TSS_Public_Copy(TSS_CONTEXT *tssContext,
1981 			      TPM_HANDLE outHandle,
1982 			      const char *outString,
1983 			      TPM_HANDLE inHandle,
1984 			      const char *inString)
1985 {
1986     TPM_RC 		rc = 0;
1987     TPM2B_PUBLIC 	public;
1988 
1989     if (rc == 0) {
1990 	rc = TSS_Public_Load(tssContext, &public, inHandle, inString);
1991     }
1992     if (rc == 0) {
1993 	rc = TSS_Public_Store(tssContext, &public, outHandle, outString);
1994     }
1995     return rc;
1996 }
1997 
1998 /* TSS_Public_Store() stores the 'public' parameter in the TSS context.
1999  */
2000 
2001 #ifdef TPM_TSS_NOFILE
2002 
TSS_Public_Store(TSS_CONTEXT * tssContext,TPM2B_PUBLIC * public,TPM_HANDLE handle,const char * string)2003 static TPM_RC TSS_Public_Store(TSS_CONTEXT *tssContext,
2004 			       TPM2B_PUBLIC *public,
2005 			       TPM_HANDLE handle,
2006 			       const char *string)
2007 {
2008     TPM_RC 	rc = 0;
2009     size_t	slotIndex;
2010 
2011     if (rc == 0) {
2012 	if (string == NULL) {
2013 	    if (handle != 0) {
2014 		/* if this handle is already used, overwrite the slot */
2015 		rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
2016 		if (rc != 0) {
2017 		    rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, TPM_RH_NULL);
2018 		    if (rc == 0) {
2019 			tssContext->objectPublic[slotIndex].objectHandle = handle;
2020 		    }
2021 		    else {
2022 			if (tssVerbose)
2023 			    printf("TSS_Public_Store: Error, no slot available for handle %08x\n",
2024 				   handle);
2025 		    }
2026 		}
2027 	    }
2028 	    else {
2029 		if (tssVerbose) printf("TSS_Public_Store: handle and string are both null");
2030 		rc = TSS_RC_NAME_FILENAME;
2031 	    }
2032 	}
2033 	else {
2034 	    if (handle == 0) {
2035 		if (tssVerbose) printf("TSS_Public_Store: string not implemented yet");
2036 		rc = TSS_RC_NAME_FILENAME;
2037 	    }
2038 	    else {
2039 		if (tssVerbose) printf("TSS_Public_Store: handle and string are both not null");
2040 		rc = TSS_RC_NAME_FILENAME;
2041 	    }
2042 	}
2043     }
2044     if (rc == 0) {
2045 	tssContext->objectPublic[slotIndex].objectPublic = *public;
2046     }
2047     return rc;
2048 }
2049 
2050 #endif
2051 
2052 /* TSS_Public_Load() loaded the object public from the TSS context.
2053 
2054  */
2055 
2056 #ifdef TPM_TSS_NOFILE
2057 
TSS_Public_Load(TSS_CONTEXT * tssContext,TPM2B_PUBLIC * public,TPM_HANDLE handle,const char * string)2058 static TPM_RC TSS_Public_Load(TSS_CONTEXT *tssContext,
2059 			      TPM2B_PUBLIC *public,
2060 			      TPM_HANDLE handle,
2061 			      const char *string)
2062 {
2063     TPM_RC 	rc = 0;
2064     size_t	slotIndex;
2065 
2066     if (rc == 0) {
2067 	if (string == NULL) {
2068 	    if (handle != 0) {
2069 		rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
2070 		if (rc != 0) {
2071 		    if (tssVerbose)
2072 			printf("TSS_Public_Load: Error, no slot found for handle %08x\n",
2073 			       handle);
2074 		}
2075 	    }
2076 	    else {
2077 		if (tssVerbose) printf("TSS_Public_Load: handle and string are both null\n");
2078 		rc = TSS_RC_NAME_FILENAME;
2079 	    }
2080 	}
2081 	else {
2082 	    if (handle == 0) {
2083 		if (tssVerbose) printf("TSS_Public_Load: string not implemented yet");
2084 		rc = TSS_RC_NAME_FILENAME;
2085 	    }
2086 	    else {
2087 		if (tssVerbose) printf("TSS_Public_Load: handle and string are both not null\n");
2088 		rc = TSS_RC_NAME_FILENAME;
2089 	    }
2090 	}
2091     }
2092     if (rc == 0) {
2093 	*public = tssContext->objectPublic[slotIndex].objectPublic;
2094     }
2095     return rc;
2096 }
2097 
2098 #endif 	/* TPM_TSS_NOFILE */
2099 
2100 #ifdef TPM_TSS_NOFILE
2101 
2102 /* TSS_ObjectPublic_GetSlotForHandle() finds the object public slot corresponding to the handle.
2103 
2104    Returns non-zero if no slot is found.
2105 */
2106 
TSS_ObjectPublic_GetSlotForHandle(TSS_CONTEXT * tssContext,size_t * slotIndex,TPM_HANDLE handle)2107 static TPM_RC TSS_ObjectPublic_GetSlotForHandle(TSS_CONTEXT *tssContext,
2108 						size_t *slotIndex,
2109 						TPM_HANDLE handle)
2110 {
2111     size_t 	i;
2112 
2113     /* search all slots for handle */
2114     for (i = 0 ; i < (sizeof(tssContext->sessions) / sizeof(TSS_SESSIONS)) ; i++) {
2115 	if (tssContext->objectPublic[i].objectHandle == handle) {
2116 	    *slotIndex = i;
2117 	    return 0;
2118 	}
2119     }
2120     return TSS_RC_NO_OBJECTPUBLIC_SLOT;
2121 }
2122 
2123 #endif
2124 
2125 #ifdef TPM_TSS_NOFILE
2126 
TSS_ObjectPublic_DeleteData(TSS_CONTEXT * tssContext,TPM_HANDLE handle)2127 static TPM_RC TSS_ObjectPublic_DeleteData(TSS_CONTEXT *tssContext, TPM_HANDLE handle)
2128 {
2129     TPM_RC	rc = 0;
2130     size_t	slotIndex;
2131 
2132     if (rc == 0) {
2133 	rc = TSS_ObjectPublic_GetSlotForHandle(tssContext, &slotIndex, handle);
2134 	if (rc != 0) {
2135 	    if (tssVerbose)
2136 		printf("TSS_ObjectPublic_DeleteData: Error, no slot found for handle %08x\n",
2137 		       handle);
2138 	}
2139     }
2140     if (rc == 0) {
2141 	tssContext->objectPublic[slotIndex].objectHandle = TPM_RH_NULL;
2142     }
2143     return rc;
2144 }
2145 
2146 #endif
2147 
2148 
2149 /* TSS_DeleteHandle() removes retained state stored by the TSS for a handle
2150  */
2151 
TSS_DeleteHandle(TSS_CONTEXT * tssContext,TPM_HANDLE handle)2152 static TPM_RC TSS_DeleteHandle(TSS_CONTEXT *tssContext,
2153 			       TPM_HANDLE handle)
2154 {
2155     TPM_RC		rc = 0;
2156     TPM_HT 		handleType;
2157 #ifndef TPM_TSS_NOFILE
2158     char		filename[TPM_DATA_DIR_PATH_LENGTH];
2159 #endif
2160 
2161     handleType = (TPM_HT) ((handle & HR_RANGE_MASK) >> HR_SHIFT);
2162 #ifndef TPM_TSS_NOFILE
2163     /* delete the Name */
2164     if (rc == 0) {
2165 	sprintf(filename, "%s/h%08x.bin", tssContext->tssDataDirectory, handle);
2166 	if (tssVverbose) printf("TSS_DeleteHandle: delete Name file %s\n", filename);
2167 	rc = TSS_File_DeleteFile(filename);
2168     }
2169     /* delete the public if it exists */
2170     if (rc == 0) {
2171 	if ((handleType == TPM_HT_TRANSIENT) ||
2172 	    (handleType == TPM_HT_PERSISTENT)) {
2173 	    sprintf(filename, "%s/hp%08x.bin", tssContext->tssDataDirectory, handle);
2174 	    if (tssVverbose) printf("TSS_DeleteHandle: delete public file %s\n", filename);
2175 	    TSS_File_DeleteFile(filename);
2176 	}
2177     }
2178 #else
2179     /* sessions persist in the context and can be deleted */
2180     if (rc == 0) {
2181 	switch (handleType) {
2182 	  case TPM_HT_NV_INDEX:
2183 	    rc = TSS_RC_NOT_IMPLEMENTED;
2184 	    break;
2185 	  case TPM_HT_HMAC_SESSION:
2186 	  case TPM_HT_POLICY_SESSION:
2187 	    if (tssVverbose) printf("TSS_DeleteHandle: delete session state %08x\n", handle);
2188 	    rc = TSS_HmacSession_DeleteData(tssContext, handle);
2189 	    break;
2190 	  case TPM_HT_TRANSIENT:
2191 	  case TPM_HT_PERSISTENT:
2192 	    rc = TSS_ObjectPublic_DeleteData(tssContext, handle);
2193 	    break;
2194 	}
2195     }
2196 #endif
2197     return rc;
2198 }
2199 
2200 #ifndef TPM_TSS_NOCRYPTO
2201 
2202 /* TSS_ObjectPublic_GetName() calculates the Name from the TPMT_PUBLIC.  The Name provides security,
2203    because the Name returned from the TPM2_ReadPublic cannot be trusted.
2204 */
2205 
TSS_ObjectPublic_GetName(TPM2B_NAME * name,TPMT_PUBLIC * tpmtPublic)2206 static TPM_RC TSS_ObjectPublic_GetName(TPM2B_NAME *name,
2207 				       TPMT_PUBLIC *tpmtPublic)
2208 {
2209     TPM_RC 	rc = 0;
2210 
2211     uint16_t 	written = 0;
2212     TPMT_HA	digest;
2213     uint32_t 	sizeInBytes = 0;
2214     uint8_t 	*buffer = NULL;
2215 
2216     if (rc == 0) {
2217 	rc = TSS_Malloc(&buffer, MAX_RESPONSE_SIZE);	/* freed @1 */
2218     }
2219     /* marshal the TPMT_PUBLIC */
2220     if (rc == 0) {
2221 	uint32_t 	size = MAX_RESPONSE_SIZE;
2222 	uint8_t 	*buffer1 = buffer;
2223 	rc = TSS_TPMT_PUBLIC_Marshalu(tpmtPublic, &written, &buffer1, &size);
2224     }
2225     /* hash the public area */
2226     if (rc == 0) {
2227 	sizeInBytes = TSS_GetDigestSize(tpmtPublic->nameAlg);
2228 	digest.hashAlg = tpmtPublic->nameAlg;	/* Name digest algorithm */
2229 	/* generate the TPMT_HA */
2230 	rc = TSS_Hash_Generate(&digest,
2231 			       written, buffer,
2232 			       0, NULL);
2233     }
2234     if (rc == 0) {
2235 	TPMI_ALG_HASH nameAlgNbo;
2236 	/* copy the digest */
2237 	memcpy(name->t.name + sizeof(TPMI_ALG_HASH), (uint8_t *)&digest.digest, sizeInBytes);
2238 	/* copy the hash algorithm */
2239 	nameAlgNbo = htons(tpmtPublic->nameAlg);
2240 	memcpy(name->t.name, (uint8_t *)&nameAlgNbo, sizeof(TPMI_ALG_HASH));
2241 	/* set the size */
2242 	name->t.size = sizeInBytes + sizeof(TPMI_ALG_HASH);
2243     }
2244     free(buffer);	/* @1 */
2245     return rc;
2246 }
2247 
2248 #endif	/* TPM_TSS_NOCRYPTO */
2249 
2250 
2251 /* TSS_NVPublic_Store() stores the NV public data in a file.
2252 
2253  */
2254 
2255 #ifndef TPM_TSS_NOFILE
2256 #ifndef TPM_TSS_NOCRYPTO
2257 
TSS_NVPublic_Store(TSS_CONTEXT * tssContext,TPMS_NV_PUBLIC * nvPublic,TPMI_RH_NV_INDEX nvIndex)2258 static TPM_RC TSS_NVPublic_Store(TSS_CONTEXT *tssContext,
2259 				 TPMS_NV_PUBLIC *nvPublic,
2260 				 TPMI_RH_NV_INDEX nvIndex)
2261 {
2262     TPM_RC 	rc = 0;
2263     char 	nvpFilename[TPM_DATA_DIR_PATH_LENGTH];
2264 
2265     if (rc == 0) {
2266 	sprintf(nvpFilename, "%s/nvp%08x.bin", tssContext->tssDataDirectory, nvIndex);
2267 	rc = TSS_File_WriteStructure(nvPublic,
2268 				     (MarshalFunction_t)TSS_TPMS_NV_PUBLIC_Marshalu,
2269 				     nvpFilename);
2270     }
2271     return rc;
2272 }
2273 
2274 #endif
2275 #endif
2276 
2277 /* TSS_NVPublic_Load() loads the NV public from a file.
2278 
2279  */
2280 
2281 #ifndef TPM_TSS_NOFILE
2282 #ifndef TPM_TSS_NOCRYPTO
2283 
TSS_NVPublic_Load(TSS_CONTEXT * tssContext,TPMS_NV_PUBLIC * nvPublic,TPMI_RH_NV_INDEX nvIndex)2284 static TPM_RC TSS_NVPublic_Load(TSS_CONTEXT *tssContext,
2285 				TPMS_NV_PUBLIC *nvPublic,
2286 				TPMI_RH_NV_INDEX nvIndex)
2287 {
2288     TPM_RC 	rc = 0;
2289     char 	nvpFilename[TPM_DATA_DIR_PATH_LENGTH];
2290 
2291     if (rc == 0) {
2292 	sprintf(nvpFilename, "%s/nvp%08x.bin", tssContext->tssDataDirectory, nvIndex);
2293 	rc = TSS_File_ReadStructure(nvPublic,
2294 				    (UnmarshalFunction_t)TSS_TPMS_NV_PUBLIC_Unmarshalu,
2295 				    nvpFilename);
2296     }
2297     return rc;
2298 }
2299 
2300 #endif
2301 #endif
2302 
2303 #ifndef TPM_TSS_NOFILE
2304 
TSS_NVPublic_Delete(TSS_CONTEXT * tssContext,TPMI_RH_NV_INDEX nvIndex)2305 static TPM_RC TSS_NVPublic_Delete(TSS_CONTEXT *tssContext,
2306 				  TPMI_RH_NV_INDEX nvIndex)
2307 {
2308     TPM_RC 	rc = 0;
2309     char 	nvpFilename[TPM_DATA_DIR_PATH_LENGTH];
2310 
2311     if (rc == 0) {
2312 	sprintf(nvpFilename, "%s/nvp%08x.bin", tssContext->tssDataDirectory, nvIndex);
2313 	rc = TSS_File_DeleteFile(nvpFilename);
2314     }
2315     return rc;
2316 }
2317 
2318 #endif
2319 
2320 #ifdef TPM_TSS_NOFILE
2321 #ifndef TPM_TSS_NOCRYPTO
2322 
2323 /* TSS_NVPublic_Store() stores the NV public data in a file.
2324 
2325  */
2326 
TSS_NVPublic_Store(TSS_CONTEXT * tssContext,TPMS_NV_PUBLIC * nvPublic,TPMI_RH_NV_INDEX nvIndex)2327 static TPM_RC TSS_NVPublic_Store(TSS_CONTEXT *tssContext,
2328 				 TPMS_NV_PUBLIC *nvPublic,
2329 				 TPMI_RH_NV_INDEX nvIndex)
2330 {
2331     TPM_RC 	rc = 0;
2332     size_t	slotIndex;
2333 
2334     if (rc == 0) {
2335 	rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, nvIndex);
2336 	if (rc != 0) {
2337 	    rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, TPM_RH_NULL);
2338 	    if (rc == 0) {
2339 		tssContext->nvPublic[slotIndex].nvIndex = nvIndex;
2340 	    }
2341 	    else {
2342 		if (tssVerbose)
2343 		    printf("TSS_NVPublic_Store: Error, no slot available for handle %08x\n",
2344 			   nvIndex);
2345 	    }
2346 	}
2347     }
2348     if (rc == 0) {
2349 	tssContext->nvPublic[slotIndex].nvPublic = *nvPublic;
2350     }
2351     return rc;
2352 }
2353 
2354 #endif
2355 #endif
2356 
2357 #ifdef TPM_TSS_NOFILE
2358 #ifndef TPM_TSS_NOCRYPTO
2359 
2360 /* TSS_NVPublic_Load() loads the NV public from a file.
2361 
2362  */
2363 
TSS_NVPublic_Load(TSS_CONTEXT * tssContext,TPMS_NV_PUBLIC * nvPublic,TPMI_RH_NV_INDEX nvIndex)2364 static TPM_RC TSS_NVPublic_Load(TSS_CONTEXT *tssContext,
2365 				TPMS_NV_PUBLIC *nvPublic,
2366 				TPMI_RH_NV_INDEX nvIndex)
2367 {
2368     TPM_RC 	rc = 0;
2369     size_t	slotIndex;
2370 
2371     if (rc == 0) {
2372 	rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, nvIndex);
2373 	if (rc != 0) {
2374 	    if (tssVerbose)
2375 		printf("TSS_NVPublic_Load: Error, no slot found for handle %08x\n",
2376 		       nvIndex);
2377 	}
2378     }
2379     if (rc == 0) {
2380 	*nvPublic = tssContext->nvPublic[slotIndex].nvPublic;
2381     }
2382     return rc;
2383 }
2384 
2385 #endif
2386 #endif
2387 
2388 #ifdef TPM_TSS_NOFILE
2389 
TSS_NVPublic_Delete(TSS_CONTEXT * tssContext,TPMI_RH_NV_INDEX nvIndex)2390 static TPM_RC TSS_NVPublic_Delete(TSS_CONTEXT *tssContext,
2391 				  TPMI_RH_NV_INDEX nvIndex)
2392 {
2393     TPM_RC 	rc = 0;
2394     size_t	slotIndex;
2395 
2396     if (rc == 0) {
2397 	rc = TSS_NvPublic_GetSlotForHandle(tssContext, &slotIndex, nvIndex);
2398 	if (rc != 0) {
2399 	    if (tssVerbose)
2400 		printf("TSS_NVPublic_Delete: Error, no slot found for handle %08x\n",
2401 		       nvIndex);
2402 	}
2403     }
2404     if (rc == 0) {
2405 	tssContext->nvPublic[slotIndex].nvIndex = TPM_RH_NULL;
2406     }
2407     return rc;
2408 }
2409 
2410 #endif
2411 
2412 #ifdef TPM_TSS_NOFILE
2413 
2414 /* TSS_NvPublic_GetSlotForHandle() finds the object public slot corresponding to the handle.
2415 
2416    Returns non-zero if no slot is found.
2417 */
2418 
TSS_NvPublic_GetSlotForHandle(TSS_CONTEXT * tssContext,size_t * slotIndex,TPMI_RH_NV_INDEX nvIndex)2419 static TPM_RC TSS_NvPublic_GetSlotForHandle(TSS_CONTEXT *tssContext,
2420 					    size_t *slotIndex,
2421 					    TPMI_RH_NV_INDEX nvIndex)
2422 {
2423     size_t 	i;
2424 
2425     /* search all slots for handle */
2426     for (i = 0 ; i < (sizeof(tssContext->nvPublic) / sizeof(TSS_NVPUBLIC)) ; i++) {
2427 	if (tssContext->nvPublic[i].nvIndex == nvIndex) {
2428 	    *slotIndex = i;
2429 	    return 0;
2430 	}
2431     }
2432     return TSS_RC_NO_NVPUBLIC_SLOT;
2433 }
2434 
2435 #endif
2436 
2437 /* TSS_NVPublic_GetName() calculates the Name from the TPMS_NV_PUBLIC.  The Name provides security,
2438    because the Name returned from the TPM2_NV_ReadPublic cannot be trusted.
2439 */
2440 
2441 #ifndef TPM_TSS_NOCRYPTO
2442 
TSS_NVPublic_GetName(TPM2B_NAME * name,TPMS_NV_PUBLIC * nvPublic)2443 static TPM_RC TSS_NVPublic_GetName(TPM2B_NAME *name,
2444 				   TPMS_NV_PUBLIC *nvPublic)
2445 {
2446     TPM_RC 	rc = 0;
2447 
2448     uint16_t 	written = 0;
2449     TPMT_HA	digest;
2450     uint32_t 	sizeInBytes = 0;
2451     uint8_t 	*buffer = NULL;
2452 
2453     if (rc == 0) {
2454 	rc = TSS_Malloc(&buffer, MAX_RESPONSE_SIZE);	/* freed @1 */
2455     }
2456     /* marshal the TPMS_NV_PUBLIC */
2457     if (rc == 0) {
2458 	uint32_t 	size = MAX_RESPONSE_SIZE;
2459 	uint8_t 	*buffer1 = buffer;
2460 	rc = TSS_TPMS_NV_PUBLIC_Marshalu(nvPublic, &written, &buffer1, &size);
2461     }
2462     /* hash the public area */
2463     if (rc == 0) {
2464 	sizeInBytes = TSS_GetDigestSize(nvPublic->nameAlg);
2465 	digest.hashAlg = nvPublic->nameAlg;	/* Name digest algorithm */
2466 	/* generate the TPMT_HA */
2467 	rc = TSS_Hash_Generate(&digest,
2468 			       written, buffer,
2469 			       0, NULL);
2470     }
2471     if (rc == 0) {
2472 	TPMI_ALG_HASH nameAlgNbo;
2473 	/* copy the digest */
2474 	memcpy(name->t.name + sizeof(TPMI_ALG_HASH), (uint8_t *)&digest.digest, sizeInBytes);
2475 	/* copy the hash algorithm */
2476 	nameAlgNbo = htons(nvPublic->nameAlg);
2477 	memcpy(name->t.name, (uint8_t *)&nameAlgNbo, sizeof(TPMI_ALG_HASH));
2478 	/* set the size */
2479 	name->t.size = sizeInBytes + sizeof(TPMI_ALG_HASH);
2480     }
2481     free(buffer);	/* @1 */
2482     return rc;
2483 }
2484 
2485 #endif
2486 
2487 #ifndef TPM_TSS_NOCRYPTO
2488 
TSS_HmacSession_SetNonceCaller(struct TSS_HMAC_CONTEXT * session,TPMS_AUTH_COMMAND * authC)2489 static TPM_RC TSS_HmacSession_SetNonceCaller(struct TSS_HMAC_CONTEXT *session,
2490 					     TPMS_AUTH_COMMAND 	*authC)
2491 {
2492     TPM_RC		rc = 0;
2493 
2494     /* generate a new nonceCaller */
2495     if (rc == 0) {
2496 	session->nonceCaller.b.size = session->sizeInBytes;
2497 	rc = TSS_RandBytes(session->nonceCaller.t.buffer, session->sizeInBytes);
2498     }
2499     /* nonceCaller for the command */
2500     if (rc == 0) {
2501 	rc = TSS_TPM2B_Copy(&authC->nonce.b, &session->nonceCaller.b, sizeof(TPMU_HA));
2502     }
2503     return rc;
2504 }
2505 
2506 #endif	/* TPM_TSS_NOCRYPTO */
2507 
2508 #ifndef TPM_TSS_NOCRYPTO
2509 
2510 /* TSS_HmacSession_SetHmacKey() calculates the session HMAC key.
2511 
2512    handleNumber is index into the session area.  The first sessions, the authorization sessions,
2513    have a corresponding handle in the command handle.
2514 */
2515 
TSS_HmacSession_SetHmacKey(TSS_CONTEXT * tssContext,struct TSS_HMAC_CONTEXT * session,size_t handleNumber,const char * password)2516 static TPM_RC TSS_HmacSession_SetHmacKey(TSS_CONTEXT *tssContext,
2517 					 struct TSS_HMAC_CONTEXT *session,
2518 					 size_t handleNumber,	/* index into the handle area */
2519 					 const char *password)
2520 {
2521     TPM_RC		rc = 0;
2522     TPM_HANDLE 		commandHandle;		/* from handle area, for bound session */
2523     TPM2B_NAME		name;
2524     TPM2B_AUTH 		authValue;
2525     int 		bindMatch = FALSE;
2526     int 		done = FALSE;		/* done with authorization sessions */
2527 
2528     /*
2529       authHMAC = HMAC sessionAlg ((sessionKey || authValue),
2530       (pHash || nonceNewer || nonceOlder
2531       { || nonceTPMdecrypt } { || nonceTPMencrypt }
2532       || sessionAttributes))
2533     */
2534     /* HMAC key is sessionKey || authValue */
2535     /* copy the session key to HMAC key */
2536     if (rc == 0) {
2537 	if (tssVverbose) TSS_PrintAll("TSS_HmacSession_SetHmacKey: sessionKey",
2538 				      session->sessionKey.b.buffer, session->sessionKey.b.size);
2539 	rc = TSS_TPM2B_Copy(&session->hmacKey.b,
2540 			    &session->sessionKey.b, sizeof(TPMU_HA) + sizeof(TPMT_HA));
2541     }
2542     /* copy the session key to sessionValue */
2543     if (rc == 0) {
2544 	rc = TSS_TPM2B_Copy(&session->sessionValue.b,
2545 			    &session->sessionKey.b, sizeof(TPMU_HA) + sizeof(TPMT_HA));
2546     }
2547     if (rc == 0) {
2548 	if (tssVverbose)
2549 	    TSS_PrintAll("TSS_HmacSession_SetHmacKey: preliminary sessionValue",
2550 			 session->sessionValue.b.buffer, session->sessionValue.b.size);
2551     }
2552     /* This value is an EmptyAuth if the HMAC is being computed to authorize an action on the
2553        object to which the session is bound.
2554     */
2555     /* The first sessions are authorization sessions.  They can have a bind entity.  All others can
2556        be encrypt or decrypt sessions, but the authValue is not included in the session key.
2557     */
2558     if (rc == 0) {
2559 	AUTH_ROLE authRole = TSS_GetAuthRole(tssContext->tssAuthContext, handleNumber);
2560 	if (authRole == AUTH_NONE) {
2561 	    if (tssVverbose) printf("TSS_HmacSession_SetHmacKey: Done, not auth session\n");
2562 	    done = TRUE;	/* not an authorization session, could be audit or
2563 				   encrypt/decrypt */
2564 	}
2565     }
2566     /* If not an authorization session, there is no authValue to append to the HMAC key or encrypt
2567        sessionValue, regardless of the binding.  Below is for auth sessions. */
2568     if (!done) {
2569 	/* First, if there was a bind handle, check if the name matches.  Else bindMatch remains
2570 	   FALSE. */
2571 	if (session->bind != TPM_RH_NULL) {
2572 	    /* get the handle for this session */
2573 	    if (tssVverbose)
2574 		printf("TSS_HmacSession_SetHmacKey: Processing bind handle %08x\n", session->bind);
2575 	    if (rc == 0) {
2576 		rc = TSS_GetCommandHandle(tssContext->tssAuthContext,
2577 					  &commandHandle,
2578 					  handleNumber);
2579 	    }
2580 	    /* get the Name corresponding to the handle */
2581 	    if (rc == 0) {
2582 		if (tssVverbose)
2583 		    printf("TSS_HmacSession_SetHmacKey: commandHandle %08x bindHandle %08x\n",
2584 			   commandHandle, session->bind);
2585 		rc = TSS_Name_GetName(tssContext, &name, commandHandle);
2586 	    }
2587 	    /* compare the authorized object name to the bind object name */
2588 	    if (rc == 0) {
2589 		bindMatch = TSS_TPM2B_Compare(&name.b, &session->bindName.b);
2590 		if (tssVverbose) printf("TSS_HmacSession_SetHmacKey: bind match %u\n", bindMatch);
2591 	    }
2592 	}
2593 	/* Second, append password to session key for HMAC key if required */
2594 
2595 	/* When performing an HMAC for authorization, the HMAC key is normally the concatenation of
2596 	   the entity's authValue to the sessions sessionKey (created at
2597 	   TPM2_StartAuthSession(). However, if the authorization is for the entity to
2598 	   which the session is bound, the authValue is not included in the HMAC key. When
2599 	   a policy requires that an HMAC be computed, it is always concatenated.
2600 	*/
2601 	if ((rc == 0) &&
2602 	    /* append if HMAC session and not bind match */
2603 	    (((session->sessionType == TPM_SE_HMAC) && !bindMatch) ||
2604 	     /* append if policy and policy authvalue */
2605 	     ((session->sessionType == TPM_SE_POLICY) && session->isAuthValueNeeded)) &&
2606 	    (password != NULL)	/* if password is NULL, nothing to append. */
2607 
2608 	    ) {
2609 
2610 	    if (tssVverbose)
2611 		printf("TSS_HmacSession_SetHmacKey: Appending authValue to HMAC key\n");
2612 	    /* convert the password to an authvalue */
2613 	    if (rc == 0) {
2614 		rc = TSS_TPM2B_StringCopy(&authValue.b, password, sizeof(authValue.t.buffer));
2615 	    }
2616 	    /* append the authvalue to the session key to create the hmac key */
2617 	    if (rc == 0) {
2618 		rc = TSS_TPM2B_Append(&session->hmacKey.b, &authValue.b,
2619 				      sizeof(TPMU_HA) + sizeof(TPMT_HA));
2620 	    }
2621 	}
2622 	/* Third, append password to session key for sessionValue
2623 
2624 	   If a session is also being used for authorization, sessionValue (see 21.2 and 21.3) is
2625 	   sessionKey || authValue. The binding of the session is ignored. If the session is not
2626 	   being used for authorization, sessionValue is sessionKey.
2627 	 */
2628 	/* NOTE This step occurs even if there is a bind match. That is, the password is effectively
2629 	   appended twice. */
2630 	if (rc == 0) {
2631 	    /* if not bind, sessionValue is sessionKey || authValue (same as HMAC key) */
2632 	    if (!bindMatch) {
2633 		if (tssVverbose)
2634 		    printf("TSS_HmacSession_SetHmacKey: "
2635 			   "No bind, appending authValue to sessionValue\n");
2636 		/* convert the password to an authvalue */
2637 		if (rc == 0) {
2638 		    rc = TSS_TPM2B_StringCopy(&authValue.b, password, sizeof(authValue.t.buffer));
2639 		}
2640 		if (rc == 0) {
2641 		    rc = TSS_TPM2B_Append(&session->sessionValue.b, &authValue.b,
2642 					  sizeof(TPMU_HA) + sizeof(TPMT_HA));
2643 		}
2644 	    }
2645 	    /* if bind, sessionValue is sessionKey || bindAuthValue */
2646 	    else {
2647 		if (tssVverbose)
2648 		    printf("TSS_HmacSession_SetHmacKey: "
2649 			   "Bind, appending bind authValue to sessionValue\n");
2650 		if (rc == 0) {
2651 		    rc = TSS_TPM2B_Append(&session->sessionValue.b, &session->bindAuthValue.b,
2652 					  sizeof(TPMU_HA) + sizeof(TPMT_HA));
2653 		}
2654 	    }
2655 	    if (rc == 0) {
2656 		if (tssVverbose)
2657 		    TSS_PrintAll("TSS_HmacSession_SetHmacKey: bindAuthValue",
2658 				 session->bindAuthValue.b.buffer, session->bindAuthValue.b.size);
2659 	    }
2660 	}
2661     }
2662     if (rc == 0) {
2663 	if (tssVverbose)
2664 	    TSS_PrintAll("TSS_HmacSession_SetHmacKey: hmacKey",
2665 			 session->hmacKey.b.buffer, session->hmacKey.b.size);
2666 	if (tssVverbose)
2667 	    TSS_PrintAll("TSS_HmacSession_SetHmacKey: sessionValue",
2668 			 session->sessionValue.b.buffer, session->sessionValue.b.size);
2669     }
2670     return rc;
2671 }
2672 
2673 #endif	/* TPM_TSS_NOCRYPTO */
2674 
2675 /* TSS_HmacSession_SetHMAC() is used for a command.  It sets all the values in one
2676    TPMS_AUTH_COMMAND, ready for marshaling into the command packet.
2677 
2678    - gets cpBuffer
2679    - generates cpHash
2680    - generates the HMAC
2681    - copies the result into authCommand
2682 
2683    Unused names must have size 0.
2684 
2685    The HMAC key is already in the session structure.
2686 */
2687 
TSS_HmacSession_SetHMAC(TSS_AUTH_CONTEXT * tssAuthContext,struct TSS_HMAC_CONTEXT * session[],TPMS_AUTH_COMMAND * authCommand[],TPMI_SH_AUTH_SESSION sessionHandle[],unsigned int sessionAttributes[],const char * password[],TPM2B_NAME * name0,TPM2B_NAME * name1,TPM2B_NAME * name2)2688 static TPM_RC TSS_HmacSession_SetHMAC(TSS_AUTH_CONTEXT *tssAuthContext,	/* authorization context */
2689 				      struct TSS_HMAC_CONTEXT *session[],
2690 				      TPMS_AUTH_COMMAND *authCommand[],	/* output: command
2691 									   authorization */
2692 				      TPMI_SH_AUTH_SESSION sessionHandle[], /* session handles in
2693 									       command */
2694 				      unsigned int sessionAttributes[],	/* attributes for this
2695 									   command */
2696 				      const char *password[],
2697 				      TPM2B_NAME *name0,		/* up to 3 names */
2698 				      TPM2B_NAME *name1,	/* unused names have length 0 */
2699 				      TPM2B_NAME *name2)
2700 {
2701     TPM_RC		rc = 0;
2702     unsigned int	i = 0;
2703 #ifndef TPM_TSS_NOCRYPTO
2704     TPMT_HA 		cpHash;
2705     TPMT_HA 		hmac;
2706     TPM2B_NONCE	nonceTPMDecrypt;
2707     TPM2B_NONCE	nonceTPMEncrypt;
2708     cpHash.hashAlg = TPM_ALG_NULL;	/* for cpHash calculation optimization */
2709 #endif	/* TPM_TSS_NOCRYPTO */
2710 
2711 
2712     for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) && (sessionHandle[i] != TPM_RH_NULL) ; i++) {
2713 	uint8_t sessionAttr8;
2714 	if (tssVverbose) printf("TSS_HmacSession_SetHMAC: Step 6 session %08x\n", sessionHandle[i]);
2715 	/* password sessions were serviced in step 2. */
2716 	if (sessionHandle[i] == TPM_RS_PW) {
2717 	    continue;
2718 	}
2719 	if (tssVverbose) printf("TSS_HmacSession_SetHMAC: sessionType %02x\n",
2720 				session[i]->sessionType);
2721 	if (tssVverbose) printf("TSS_HmacSession_SetHMAC: isPasswordNeeded %02x\n",
2722 				session[i]->isPasswordNeeded);
2723 	if (tssVverbose) printf("TSS_HmacSession_SetHMAC: isAuthValueNeeded %02x\n",
2724 				session[i]->isAuthValueNeeded);
2725 	/* sessionHandle */
2726 	authCommand[i]->sessionHandle = session[i]->sessionHandle;
2727 	/* attributes come from command */
2728 	sessionAttr8 = (uint8_t)sessionAttributes[i];
2729 	authCommand[i]->sessionAttributes.val = sessionAttr8;
2730 
2731 	/* policy session with policy password handled below, no hmac.  isPasswordNeeded is never
2732 	   true for an HMAC session, so don't need to test session type here. */
2733 	if (!(session[i]->isPasswordNeeded)) {
2734 	    /* HMAC session */
2735 	    if ((session[i]->sessionType == TPM_SE_HMAC) ||
2736 		/* policy session with TPM2_PolicyAuthValue */
2737 		((session[i]->sessionType == TPM_SE_POLICY) && (session[i]->isAuthValueNeeded)) ||
2738 		/* salted session */
2739 		(session[i]->hmacKey.t.size != 0)
2740 		) {
2741 		/* needs HMAC */
2742 #ifndef TPM_TSS_NOCRYPTO
2743 		if (tssVverbose) printf("TSS_HmacSession_SetHMAC: calculate HMAC\n");
2744 		/* calculate cpHash.  Performance optimization: If there is more than one session,
2745 		   and the hash algorithm is the same, use the previously calculated version. */
2746 		if ((rc == 0) && (cpHash.hashAlg != session[i]->authHashAlg)) {
2747 		    uint32_t cpBufferSize;
2748 		    uint8_t *cpBuffer;
2749 		    TPM_CC commandCode;
2750 		    TPM_CC commandCodeNbo;
2751 
2752 		    rc = TSS_GetCpBuffer(tssAuthContext,
2753 					 &cpBufferSize,
2754 					 &cpBuffer);
2755 		    if (tssVverbose) TSS_PrintAll("TSS_HmacSession_SetHMAC: cpBuffer",
2756 						  cpBuffer, cpBufferSize);
2757 		    cpHash.hashAlg = session[i]->authHashAlg;
2758 
2759 		    /* cpHash = hash(commandCode [ || authName1		*/
2760 		    /*                           [ || authName2		*/
2761 		    /*                           [ || authName3 ]]]	*/
2762 		    /*                           [ || parameters])	*/
2763 		    /* A cpHash can contain just a commandCode only if the lone session is */
2764 		    /* an audit session. */
2765 
2766 		    commandCode = TSS_GetCommandCode(tssAuthContext);
2767 		    commandCodeNbo = htonl(commandCode);
2768 		    rc = TSS_Hash_Generate(&cpHash,		/* largest size of a digest */
2769 					   sizeof(TPM_CC), &commandCodeNbo,
2770 					   name0->b.size, &name0->b.buffer,
2771 					   name1->b.size, &name1->b.buffer,
2772 					   name2->b.size, &name2->b.buffer,
2773 					   cpBufferSize, cpBuffer,
2774 					   0, NULL);
2775 		}
2776 		if (i == 0) {
2777 		    unsigned int 	isDecrypt = 0;	/* count number of sessions with decrypt
2778 							   set */
2779 		    unsigned int	decryptSession = 0;	/* which one is decrypt */
2780 		    unsigned int 	isEncrypt = 0;	/* count number of sessions with decrypt
2781 							   set */
2782 		    unsigned int	encryptSession = 0;	/* which one is decrypt */
2783 		    nonceTPMDecrypt.t.size = 0;
2784 		    nonceTPMEncrypt.t.size = 0;
2785 		    /* if a different session is being used for parameter decryption, then the
2786 		       nonceTPM for that session is included in the HMAC of the first authorization
2787 		       session */
2788 		    if (rc == 0) {
2789 			rc = TSS_Sessions_GetDecryptSession(&isDecrypt,
2790 							    &decryptSession,
2791 							    sessionHandle,
2792 							    sessionAttributes);
2793 		    }
2794 		    if ((rc == 0) && isDecrypt && (decryptSession != 0)) {
2795 			rc = TSS_TPM2B_Copy(&nonceTPMDecrypt.b,
2796 					    &session[decryptSession]->nonceTPM.b, sizeof(TPMU_HA));
2797 		    }
2798 		    /* if a different session is being used for parameter encryption, then the
2799 		       nonceTPM for that session is included in the HMAC of the first authorization
2800 		       session */
2801 		    if (rc == 0) {
2802 			rc = TSS_Sessions_GetEncryptSession(&isEncrypt,
2803 							    &encryptSession,
2804 							    sessionHandle,
2805 							    sessionAttributes);
2806 		    }
2807 		    /* Don't include the same nonce twice */
2808 		    if ((rc == 0) && isEncrypt && (encryptSession != 0)) {
2809 			if (!isDecrypt || (encryptSession != decryptSession)) {
2810 			    rc = TSS_TPM2B_Copy(&nonceTPMEncrypt.b,
2811 						&session[encryptSession]->nonceTPM.b,
2812 						sizeof(TPMU_HA));
2813 			}
2814 		    }
2815 		}
2816 		/* for other than the first session, those nonces are not used */
2817 		else {
2818 		    nonceTPMDecrypt.t.size = 0;
2819 		    nonceTPMEncrypt.t.size = 0;
2820 		}
2821 		/* */
2822 		if (rc == 0) {
2823 		    hmac.hashAlg = session[i]->authHashAlg;
2824 		    rc = TSS_HMAC_Generate(&hmac,				/* output hmac */
2825 					   &session[i]->hmacKey,		/* input key */
2826 					   session[i]->sizeInBytes, (uint8_t *)&cpHash.digest,
2827 					   /* new is nonceCaller */
2828 					   session[i]->nonceCaller.b.size,
2829 					   &session[i]->nonceCaller.b.buffer,
2830 					   /* old is previous nonceTPM */
2831 					   session[i]->nonceTPM.b.size,
2832 					   &session[i]->nonceTPM.b.buffer,
2833 					   /* nonceTPMDecrypt */
2834 					   nonceTPMDecrypt.b.size, nonceTPMDecrypt.b.buffer,
2835 					   /* nonceTPMEncrypt */
2836 					   nonceTPMEncrypt.b.size, nonceTPMEncrypt.b.buffer,
2837 					   /* 1 byte, no endian conversion */
2838 					   sizeof(uint8_t), &sessionAttr8,
2839 					   0, NULL);
2840 		    if (tssVverbose) {
2841 			TSS_PrintAll("TSS_HmacSession_SetHMAC: HMAC key",
2842 				     session[i]->hmacKey.t.buffer, session[i]->hmacKey.t.size);
2843 			TSS_PrintAll("TSS_HmacSession_SetHMAC: cpHash",
2844 				     (uint8_t *)&cpHash.digest, session[i]->sizeInBytes);
2845 			TSS_PrintAll("TSS_HmacSession_Set: nonceCaller",
2846 				     session[i]->nonceCaller.b.buffer,
2847 				     session[i]->nonceCaller.b.size);
2848 			TSS_PrintAll("TSS_HmacSession_SetHMAC: nonceTPM",
2849 				     session[i]->nonceTPM.b.buffer, session[i]->nonceTPM.b.size);
2850 			TSS_PrintAll("TSS_HmacSession_SetHMAC: nonceTPMDecrypt",
2851 				     nonceTPMDecrypt.b.buffer, nonceTPMDecrypt.b.size);
2852 			TSS_PrintAll("TSS_HmacSession_SetHMAC: nonceTPMEncrypt",
2853 				     nonceTPMEncrypt.b.buffer, nonceTPMEncrypt.b.size);
2854 			TSS_PrintAll("TSS_HmacSession_SetHMAC: sessionAttributes",
2855 				     &sessionAttr8, sizeof(uint8_t));
2856 			TSS_PrintAll("TSS_HmacSession_SetHMAC: HMAC",
2857 				     (uint8_t *)&hmac.digest, session[i]->sizeInBytes);
2858 		    }
2859 		}
2860 		/* copy HMAC into authCommand TPM2B_AUTH hmac */
2861 		if (rc == 0) {
2862 		    rc = TSS_TPM2B_Create(&authCommand[i]->hmac.b,
2863 					  (uint8_t *)&hmac.digest,
2864 					  session[i]->sizeInBytes,
2865 					  sizeof(authCommand[i]->hmac.t.buffer));
2866 		}
2867 #else
2868 		tssAuthContext = tssAuthContext;
2869 		name0 = name0;
2870 		name1 = name1;
2871 		name2 = name2;
2872 		if (tssVerbose)
2873 		    printf("TSS_HmacSession_SetHMAC: Error, with no crypto not implemented\n");
2874 		rc = TSS_RC_NOT_IMPLEMENTED;
2875 #endif	/* TPM_TSS_NOCRYPTO */
2876 	    }
2877 	    /* not HMAC, not policy requiring password or hmac */
2878 	    else {
2879 		authCommand[i]->hmac.b.size = 0;
2880 	    }
2881 	}
2882 	/* For a policy session that contains TPM2_PolicyPassword(), the password takes precedence
2883 	   and must be present in hmac. */
2884 	else {		/* isPasswordNeeded true */
2885 	    if (tssVverbose) printf("TSS_HmacSession_SetHMAC: use password\n");
2886 	    /* nonce has already been set */
2887 	    rc = TSS_TPM2B_StringCopy(&authCommand[i]->hmac.b,
2888 				      password[i], sizeof(authCommand[i]->hmac.t.buffer));
2889 	}
2890     }
2891     return rc;
2892 }
2893 
2894 
2895 #ifndef TPM_TSS_NOCRYPTO
2896 
2897 /* TSS_HmacSession_Verify() is used for a response.  It uses the values in TPMS_AUTH_RESPONSE to
2898    validate the response HMAC
2899 */
2900 
TSS_HmacSession_Verify(TSS_AUTH_CONTEXT * tssAuthContext,struct TSS_HMAC_CONTEXT * session,TPMS_AUTH_RESPONSE * authResponse)2901 static TPM_RC TSS_HmacSession_Verify(TSS_AUTH_CONTEXT *tssAuthContext,	/* authorization context */
2902 				     struct TSS_HMAC_CONTEXT *session,	/* TSS session context */
2903 				     TPMS_AUTH_RESPONSE *authResponse)	/* input: response authorization */
2904 {
2905     TPM_RC		rc = 0;
2906     uint32_t		rpBufferSize;
2907     uint8_t 		*rpBuffer;
2908     TPMT_HA 		rpHash;
2909     TPMT_HA 		actualHmac;
2910 
2911     /* get the rpBuffer */
2912     if (rc == 0) {
2913 	rc = TSS_GetRpBuffer(tssAuthContext, &rpBufferSize, &rpBuffer);
2914 	if (tssVverbose) TSS_PrintAll("TSS_HmacSession_Verify: rpBuffer",
2915 				      rpBuffer, rpBufferSize);
2916     }
2917     /* calculate rpHash */
2918     if (rc == 0) {
2919 	TPM_CC commandCode;
2920 	TPM_CC commandCodeNbo;
2921 	rpHash.hashAlg = session->authHashAlg;
2922 
2923 	commandCode = TSS_GetCommandCode(tssAuthContext);
2924 	commandCodeNbo = htonl(commandCode);
2925 
2926 	/* rpHash = HsessionAlg (responseCode || commandCode {|| parameters })	 */
2927 	rc = TSS_Hash_Generate(&rpHash,			/* largest size of a digest */
2928 			       sizeof(TPM_RC), &rc,	/* RC is always 0, no need to endian
2929 							   convert */
2930 			       sizeof(TPM_CC), &commandCodeNbo,
2931 			       rpBufferSize, rpBuffer,
2932 			       0, NULL);
2933     }
2934     /* construct the actual HMAC as TPMT_HA */
2935     if (rc == 0) {
2936 	actualHmac.hashAlg = session->authHashAlg;
2937 	if (authResponse->hmac.t.size != session->sizeInBytes) {
2938 	    if (tssVerbose)
2939 		printf("TSS_HmacSession_Verify: HMAC size %u inconsistent with algorithm %u\n",
2940 		       authResponse->hmac.t.size, session->sizeInBytes);
2941 	    rc = TSS_RC_HMAC_SIZE;
2942 	}
2943     }
2944     if (rc == 0) {
2945 	memcpy((uint8_t *)&actualHmac.digest, &authResponse->hmac.t.buffer,
2946 	       authResponse->hmac.t.size);
2947     }
2948     /* verify the HMAC */
2949     if (rc == 0) {
2950 	if (tssVverbose) {
2951 	    TSS_PrintAll("TSS_HmacSession_Verify: HMAC key",
2952 			 session->hmacKey.t.buffer, session->hmacKey.t.size);
2953 	    TSS_PrintAll("TSS_HmacSession_Verify: rpHash",
2954 			 (uint8_t *)&rpHash.digest, session->sizeInBytes);
2955 	    TSS_PrintAll("TSS_HmacSession_Verify: nonceTPM",
2956 			 session->nonceTPM.b.buffer, session->nonceTPM.b.size);
2957 	    TSS_PrintAll("TSS_HmacSession_Verify: nonceCaller",
2958 			 session->nonceCaller.b.buffer, session->nonceCaller.b.size);
2959 	    TSS_PrintAll("TSS_HmacSession_Verify: sessionAttributes",
2960 			 &authResponse->sessionAttributes.val, sizeof(uint8_t));
2961 	    TSS_PrintAll("TSS_HmacSession_Verify: response HMAC",
2962 			 (uint8_t *)&authResponse->hmac.t.buffer, session->sizeInBytes);
2963 	}
2964 	rc = TSS_HMAC_Verify(&actualHmac,		/* input response hmac */
2965 			     &session->hmacKey,		/* input HMAC key */
2966 			     session->sizeInBytes,
2967 			     /* rpHash */
2968 			     session->sizeInBytes, (uint8_t *)&rpHash.digest,
2969 			     /* new is nonceTPM */
2970 			     session->nonceTPM.b.size, &session->nonceTPM.b.buffer,
2971 			     /* old is nonceCaller */
2972 			     session->nonceCaller.b.size, &session->nonceCaller.b.buffer,
2973 			     /* 1 byte, no endian conversion */
2974 			     sizeof(uint8_t), &authResponse->sessionAttributes.val,
2975 			     0, NULL);
2976     }
2977     return rc;
2978 }
2979 
2980 #endif 	/* TPM_TSS_NOCRYPTO */
2981 
2982 /* TSS_HmacSession_Continue() handles the response continueSession flag.  It either saves the
2983    updated session or deletes the session state. */
2984 
TSS_HmacSession_Continue(TSS_CONTEXT * tssContext,struct TSS_HMAC_CONTEXT * session,TPMS_AUTH_RESPONSE * authR)2985 static TPM_RC TSS_HmacSession_Continue(TSS_CONTEXT *tssContext,
2986 				       struct TSS_HMAC_CONTEXT *session,
2987 				       TPMS_AUTH_RESPONSE *authR)
2988 {
2989     TPM_RC		rc = 0;
2990 
2991     if (rc == 0) {
2992 	/* if continue set */
2993 	if (authR->sessionAttributes.val & TPMA_SESSION_CONTINUESESSION) {
2994 	    /* clear the policy flags in preparation for the next use */
2995 	    session->isPasswordNeeded = FALSE;
2996 	    session->isAuthValueNeeded = FALSE;
2997 	    /* save the session */
2998 	    rc = TSS_HmacSession_SaveSession(tssContext, session);
2999 	}
3000 	else {		/* continue clear */
3001 	    /* delete the session state */
3002 	    rc = TSS_DeleteHandle(tssContext, session->sessionHandle);
3003 	}
3004     }
3005     return rc;
3006 }
3007 
3008 /* TSS_Sessions_GetDecryptSession() searches for a command decrypt session.  If found, returns
3009    isDecrypt TRUE, and the session number in decryptSession.
3010 
3011 */
3012 
TSS_Sessions_GetDecryptSession(unsigned int * isDecrypt,unsigned int * decryptSession,TPMI_SH_AUTH_SESSION sessionHandle[],unsigned int sessionAttributes[])3013 static TPM_RC TSS_Sessions_GetDecryptSession(unsigned int *isDecrypt,
3014 					     unsigned int *decryptSession,
3015 					     TPMI_SH_AUTH_SESSION sessionHandle[],
3016 					     unsigned int sessionAttributes[])
3017 {
3018     TPM_RC		rc = 0;
3019     unsigned int 	i = 0;
3020 
3021     /* count the number of command decrypt sessions */
3022     *isDecrypt = 0;		/* number of sessions with decrypt set */
3023     for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) &&
3024 	     (sessionHandle[i] != TPM_RH_NULL) &&
3025 	     (sessionHandle[i] != TPM_RS_PW) ;
3026 	     i++) {
3027 	if (sessionAttributes[i] & TPMA_SESSION_DECRYPT) {
3028 	    (*isDecrypt)++;		/* count number of decrypt sessions */
3029 	    *decryptSession = i;	/* record which one it was */
3030 	}
3031     }
3032     /* how many decrypt sessions were found */
3033     if (rc == 0) {
3034 	if (tssVverbose) printf("TSS_Sessions_GetDecryptSession: Found %u decrypt sessions at %u\n",
3035 				*isDecrypt, *decryptSession);
3036 	if (*isDecrypt > 1) {
3037 	    if (tssVerbose)
3038 		printf("TSS_Sessions_GetDecryptSession: Error, found %u decrypt sessions\n",
3039 		       *isDecrypt);
3040 	    rc = TSS_RC_DECRYPT_SESSIONS;
3041 	}
3042     }
3043     return rc;
3044 }
3045 
3046 /* TSS_Sessions_GetEncryptSession() searches for a response encrypt session.  If found, returns
3047    isEncrypt TRUE, and the session number in encryptSession.
3048 
3049 */
3050 
TSS_Sessions_GetEncryptSession(unsigned int * isEncrypt,unsigned int * encryptSession,TPMI_SH_AUTH_SESSION sessionHandle[],unsigned int sessionAttributes[])3051 static TPM_RC TSS_Sessions_GetEncryptSession(unsigned int *isEncrypt,
3052 					     unsigned int *encryptSession,
3053 					     TPMI_SH_AUTH_SESSION sessionHandle[],
3054 					     unsigned int sessionAttributes[])
3055 {
3056     TPM_RC		rc = 0;
3057     unsigned int 	i = 0;
3058 
3059     /* count the number of command encrypt sessions */
3060     *isEncrypt = 0;		/* number of sessions with encrypt set */
3061     for (i = 0 ; (rc == 0) && (i < MAX_SESSION_NUM) &&
3062 	     (sessionHandle[i] != TPM_RH_NULL) &&
3063 	     (sessionHandle[i] != TPM_RS_PW) ;
3064 	 i++) {
3065 	if (sessionAttributes[i] & TPMA_SESSION_ENCRYPT) {
3066 	    (*isEncrypt)++;		/* count number of encrypt sessions */
3067 	    *encryptSession = i;	/* record which one it was */
3068 	}
3069     }
3070     /* how many encrypt sessions were found */
3071     if (rc == 0) {
3072 	if (tssVverbose) printf("TSS_Sessions_GetEncryptSession: Found %u encrypt sessions at %u\n",
3073 				*isEncrypt, *encryptSession);
3074 	if (*isEncrypt > 1) {
3075 	    if (tssVerbose)
3076 		printf("TSS_Sessions_GetEncryptSession: Error, found %u encrypt sessions\n",
3077 		       *isEncrypt);
3078 	    rc = TSS_RC_ENCRYPT_SESSIONS;
3079 	}
3080     }
3081     return rc;
3082 }
3083 
3084 /* TSS_Command_Decrypt() determines whether any sessions are command decrypt sessions.  If so, it
3085    encrypts the first command parameter.
3086 
3087    It does common error checking, then calls algorithm specific functions.
3088 
3089 */
3090 
TSS_Command_Decrypt(TSS_AUTH_CONTEXT * tssAuthContext,struct TSS_HMAC_CONTEXT * session[],TPMI_SH_AUTH_SESSION sessionHandle[],unsigned int sessionAttributes[])3091 static TPM_RC TSS_Command_Decrypt(TSS_AUTH_CONTEXT *tssAuthContext,
3092 				  struct TSS_HMAC_CONTEXT *session[],
3093 				  TPMI_SH_AUTH_SESSION sessionHandle[],
3094 				  unsigned int	sessionAttributes[])
3095 {
3096     TPM_RC		rc = 0;
3097     unsigned int 	isDecrypt = 0;		/* count number of sessions with decrypt set */
3098     unsigned int	decryptSession = 0;	/* which session is decrypt */
3099 
3100     /* determine if there is a decrypt session */
3101     if (rc == 0) {
3102 	rc = TSS_Sessions_GetDecryptSession(&isDecrypt,
3103 					    &decryptSession,
3104 					    sessionHandle,
3105 					    sessionAttributes);
3106     }
3107 #ifndef TPM_TSS_NOCRYPTO
3108     {
3109 	COMMAND_INDEX   tpmCommandIndex;	/* index into TPM table */
3110 	TPM_CC 		commandCode;
3111 	int		decryptSize;		/* size of TPM2B size, 2 if there is a TPM2B, 0 if
3112 						   not */
3113 	uint32_t 	paramSize;		/* size of the parameter to encrypt */
3114 	uint8_t 	*decryptParamBuffer;
3115 	/* can the command parameter be encrypted */
3116 	if ((rc == 0) && isDecrypt) {
3117 	    /* get the commandCode, stored in TSS during marshal */
3118 	    commandCode  = TSS_GetCommandCode(tssAuthContext);
3119 	    /* get the index into the TPM command attributes table */
3120 	    tpmCommandIndex = CommandCodeToCommandIndex(commandCode);
3121 	    /* can this be a decrypt command (this is size of TPM2B size, not size of parameter) */
3122 	    decryptSize = getDecryptSize(tpmCommandIndex);
3123 	    if (decryptSize != 2) {		/* only handle TPM2B */
3124 		printf("TSS_Command_Decrypt: Error, command cannot be encrypted\n");
3125 		rc = TSS_RC_NO_DECRYPT_PARAMETER;
3126 	    }
3127 	}
3128 	/* get the TPM2B parameter to encrypt */
3129 	if ((rc == 0) && isDecrypt) {
3130 	    rc = TSS_GetCommandDecryptParam(tssAuthContext, &paramSize, &decryptParamBuffer);
3131 	}
3132 	/* if the size of the parameter to encrypt is zero, nothing to encrypt */
3133 	if ((rc == 0) && isDecrypt) {
3134 	    if (paramSize == 0) {
3135 		isDecrypt = FALSE;	/* none, done with this function */
3136 	    }
3137 	}
3138 	/* error checking complete, do the encryption */
3139 	if ((rc == 0) && isDecrypt) {
3140 	    switch (session[decryptSession]->symmetric.algorithm) {
3141 	      case TPM_ALG_XOR:
3142 		rc = TSS_Command_DecryptXor(tssAuthContext, session[decryptSession]);
3143 		break;
3144 	      case TPM_ALG_AES:
3145 		rc = TSS_Command_DecryptAes(tssAuthContext, session[decryptSession]);
3146 		break;
3147 	      default:
3148 		if (tssVerbose) printf("TSS_Command_Decrypt: Error, algorithm %04x not implemented\n",
3149 				       session[decryptSession]->symmetric.algorithm);
3150 		rc = TSS_RC_BAD_DECRYPT_ALGORITHM;
3151 		break;
3152 	    }
3153 	}
3154     }
3155 #else
3156     tssAuthContext = tssAuthContext;
3157     session = session;
3158     if ((rc == 0) && isDecrypt) {
3159 	if (tssVerbose)
3160 	    printf("TSS_Command_Decrypt: Error, with no crypto not implemented\n");
3161 	rc = TSS_RC_NOT_IMPLEMENTED;
3162     }
3163 #endif
3164     return rc;
3165 }
3166 
3167 #ifndef TPM_TSS_NOCRYPTO
3168 
3169 /* NOTE: if AES also works, do in place encryption */
3170 
TSS_Command_DecryptXor(TSS_AUTH_CONTEXT * tssAuthContext,struct TSS_HMAC_CONTEXT * session)3171 static TPM_RC TSS_Command_DecryptXor(TSS_AUTH_CONTEXT *tssAuthContext,
3172 				     struct TSS_HMAC_CONTEXT *session)
3173 {
3174     TPM_RC		rc = 0;
3175     unsigned int	i;
3176     uint32_t 		paramSize;
3177     uint8_t 		*decryptParamBuffer;
3178     uint8_t 		*mask = NULL;
3179     uint8_t 		*encryptParamBuffer = NULL;
3180 
3181     /* get the TPM2B parameter to encrypt */
3182     if (rc == 0) {
3183 	rc = TSS_GetCommandDecryptParam(tssAuthContext, &paramSize, &decryptParamBuffer);
3184     }
3185     if (rc == 0) {
3186 	if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptXor: decrypt in",
3187 				      decryptParamBuffer, paramSize);
3188     }
3189     if (rc == 0) {
3190 	rc = TSS_Malloc(&mask, paramSize);
3191     }
3192     if (rc == 0) {
3193 	rc = TSS_Malloc(&encryptParamBuffer, paramSize);
3194     }
3195     /* generate the XOR pad */
3196     /* 21.2	XOR Parameter Obfuscation
3197 
3198        XOR(parameter, hashAlg, sessionValue, nonceNewer, nonceOlder)
3199 
3200        parameter	a variable sized buffer containing the parameter to be obfuscated
3201        hashAlg		the hash algorithm associated with the session
3202        sessionValue	the session-specific HMAC key
3203        nonceNewer	for commands, this will be nonceCaller and for responses it will be nonceTPM
3204        nonceOlder	for commands, this will be nonceTPM and for responses it will be nonceCaller
3205 
3206        11.4.6.3	XOR Obfuscation
3207 
3208        XOR(data, hashAlg, key, contextU, contextV)
3209 
3210        mask = KDFa (hashAlg, key, "XOR", contextU, contextV, data.size * 8)
3211     */
3212     /* KDFa for the XOR mask */
3213     if (rc == 0) {
3214 	if (tssVverbose) printf("TSS_Command_DecryptXor: hashAlg %04x\n", session->authHashAlg);
3215 	if (tssVverbose) printf("TSS_Command_DecryptXor: sizeInBits %04x\n", paramSize * 8);
3216 	if (tssVverbose)
3217 	    TSS_PrintAll("TSS_Command_DecryptXor: sessionKey",
3218 			 session->sessionKey.b.buffer, session->sessionKey.b.size);
3219 	if (tssVverbose)
3220 	    TSS_PrintAll("TSS_Command_DecryptXor: sessionValue",
3221 			 session->sessionValue.b.buffer, session->sessionValue.b.size);
3222 	rc = TSS_KDFA(mask,
3223 		      session->authHashAlg,
3224 		      &session->sessionValue.b,
3225 		      "XOR",
3226 		      &session->nonceCaller.b,
3227 		      &session->nonceTPM.b,
3228 		      paramSize * 8);
3229     }
3230     if (rc == 0) {
3231 	if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptXor: mask",
3232 				      mask, paramSize);
3233     }
3234     /* XOR */
3235     for (i = 0 ; (rc == 0) && (i < paramSize ) ; i++)  {
3236 	encryptParamBuffer[i] = decryptParamBuffer[i] ^ mask[i];
3237     }
3238     if (rc == 0) {
3239 	rc = TSS_SetCommandDecryptParam(tssAuthContext, paramSize, encryptParamBuffer);
3240     }
3241     if (rc == 0) {
3242 	if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptXor: encrypt out",
3243 				      encryptParamBuffer, paramSize);
3244     }
3245     free(mask);
3246     free(encryptParamBuffer);
3247     return rc;
3248 }
3249 
3250 #endif	/* TPM_TSS_NOCRYPTO */
3251 
3252 #ifndef TPM_TSS_NOCRYPTO
3253 
3254 /* NOTE: if AES also works, do in place encryption */
3255 
TSS_Command_DecryptAes(TSS_AUTH_CONTEXT * tssAuthContext,struct TSS_HMAC_CONTEXT * session)3256 static TPM_RC TSS_Command_DecryptAes(TSS_AUTH_CONTEXT *tssAuthContext,
3257 				     struct TSS_HMAC_CONTEXT *session)
3258 {
3259     TPM_RC		rc = 0;
3260     uint32_t 		paramSize;
3261     uint8_t 		*decryptParamBuffer;
3262     uint8_t 		*encryptParamBuffer = NULL;
3263     TPM2B_IV		iv;
3264     uint32_t           	kdfaBits;
3265     uint16_t		keySizeinBytes;
3266     uint8_t		symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];	/* AES key + IV */
3267 
3268     /* get the TPM2B parameter to encrypt */
3269     if (rc == 0) {
3270 	rc = TSS_GetCommandDecryptParam(tssAuthContext, &paramSize, &decryptParamBuffer);
3271     }
3272     if (rc == 0) {
3273 	if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptAes: decrypt in",
3274 				      decryptParamBuffer, paramSize);
3275     }
3276     if (rc == 0) {
3277 	rc = TSS_Malloc(&encryptParamBuffer, paramSize);	/* free @1 */
3278     }
3279     /* generate the encryption key and IV */
3280     /* 21.3	CFB Mode Parameter Encryption
3281 
3282        KDFa (hashAlg, sessionValue, "CFB", nonceNewer, nonceOlder, bits)	(34)
3283 
3284        hashAlg		the hash algorithm associated with the session
3285        sessionValue	the session-specific HMAC key
3286        "CFB"		label to differentiate use of KDFa() (see 4.2)
3287        nonceNewer	nonceCaller for a command and nonceTPM for a response
3288        nonceOlder	nonceTPM for a command and nonceCaller for a response
3289        bits		the number of bits required for the symmetric key plus an IV
3290     */
3291     if (rc == 0) {
3292 	iv.t.size = TSS_Sym_GetBlockSize(session->symmetric.algorithm,
3293 					 session->symmetric.keyBits.aes);
3294 	/* generate random values for both the AES key and the IV */
3295 	kdfaBits = session->symmetric.keyBits.aes + (iv.t.size * 8);
3296 
3297 	if (tssVverbose) printf("TSS_Command_DecryptAes: hashAlg %04x\n",
3298 				session->authHashAlg);
3299 	if (tssVverbose) printf("TSS_Command_DecryptAes: AES key bits %u\n",
3300 				session->symmetric.keyBits.aes);
3301 	if (tssVverbose) printf("TSS_Command_DecryptAes: kdfaBits %04x\n",
3302 				kdfaBits);
3303 	if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptAes: session key",
3304 				      session->sessionKey.b.buffer, session->sessionKey.b.size);
3305 
3306 	rc = TSS_KDFA(&symParmString[0],
3307 		      session->authHashAlg,
3308 		      &session->sessionValue.b,
3309 		      "CFB",
3310 		      &session->nonceCaller.b,
3311 		      &session->nonceTPM.b,
3312 		      kdfaBits);
3313     }
3314     /* copy the latter part of the kdf output to the IV */
3315     if (rc == 0) {
3316 	keySizeinBytes = session->symmetric.keyBits.aes / 8;
3317 	memcpy(iv.t.buffer, &symParmString[keySizeinBytes], iv.t.size);
3318 	if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptAes: IV",
3319 				      iv.t.buffer, iv.t.size);
3320     }
3321     /* AES CFB encrypt the command */
3322     if (rc == 0) {
3323 	TPM_RC crc;
3324 	crc = TSS_AES_EncryptCFB(encryptParamBuffer,			/* output */
3325 				 session->symmetric.keyBits.aes,	/* 128 */
3326 				 symParmString,				/* key */
3327 				 iv.t.buffer,				/* IV */
3328 				 paramSize,				/* length */
3329 				 (uint8_t *)decryptParamBuffer);	/* input */
3330 	if (crc != 0) {
3331 	    if (tssVerbose) printf("TSS_Command_DecryptAes: AES encrypt failed\n");
3332 	    rc = TSS_RC_AES_ENCRYPT_FAILURE;
3333 	}
3334     }
3335     if (rc == 0) {
3336 	if (tssVverbose) TSS_PrintAll("TSS_Command_DecryptAes: encrypt out",
3337 				      encryptParamBuffer, paramSize);
3338     }
3339     if (rc == 0) {
3340 	rc = TSS_SetCommandDecryptParam(tssAuthContext, paramSize, encryptParamBuffer);
3341     }
3342     free(encryptParamBuffer);	/* @1 */
3343     return rc;
3344 }
3345 
3346 #endif	/* TPM_TSS_NOCRYPTO */
3347 
TSS_Response_Encrypt(TSS_AUTH_CONTEXT * tssAuthContext,struct TSS_HMAC_CONTEXT * session[],TPMI_SH_AUTH_SESSION sessionHandle[],unsigned int sessionAttributes[])3348 static TPM_RC TSS_Response_Encrypt(TSS_AUTH_CONTEXT *tssAuthContext,
3349 				   struct TSS_HMAC_CONTEXT *session[],
3350 				   TPMI_SH_AUTH_SESSION sessionHandle[],
3351 				   unsigned int sessionAttributes[])
3352 {
3353     TPM_RC		rc = 0;
3354     unsigned int 	isEncrypt = 0;		/* count number of sessions with decrypt set */
3355     unsigned int	encryptSession = 0;	/* which one is decrypt */
3356 
3357     /* determine if there is an encrypt session */
3358     if (rc == 0) {
3359 	rc = TSS_Sessions_GetEncryptSession(&isEncrypt,
3360 					    &encryptSession,
3361 					    sessionHandle,
3362 					    sessionAttributes);
3363     }
3364 #ifndef TPM_TSS_NOCRYPTO
3365     {
3366 	COMMAND_INDEX   tpmCommandIndex;	/* index into TPM table */
3367 	TPM_CC 		commandCode;
3368 	int		encryptSize;		/* size of TPM2B size, 2 if there is a TPM2B, 0 if
3369 						   not */
3370 	uint32_t 	paramSize;		/* size of the parameter to decrypt */
3371 	uint8_t 	*encryptParamBuffer;
3372 	/* can the response parameter be decrypted */
3373 	if ((rc == 0) && isEncrypt) {
3374 	    /* get the commandCode, stored in TSS during marshal */
3375 	    commandCode  = TSS_GetCommandCode(tssAuthContext);
3376 	    /* get the index into the TPM command attributes table */
3377 	    tpmCommandIndex = CommandCodeToCommandIndex(commandCode);
3378 	    /* can this be a decrypt command */
3379 	    encryptSize = getEncryptSize(tpmCommandIndex);
3380 	    if (encryptSize == 0) {
3381 		if (tssVerbose) printf("TSS_Response_Encrypt: "
3382 				       "Error, response cannot be encrypted\n");
3383 		rc = TSS_RC_NO_ENCRYPT_PARAMETER;
3384 	    }
3385 	}
3386 	/* get the TPM2B parameter to decrypt */
3387 	if ((rc == 0) && isEncrypt) {
3388 	    rc = TSS_GetResponseEncryptParam(tssAuthContext, &paramSize, &encryptParamBuffer);
3389 	}
3390 	/* if the size of the parameter to decrypt is zero, nothing to decrypt */
3391 	if ((rc == 0) && isEncrypt) {
3392 	    if (paramSize == 0) {
3393 		isEncrypt = FALSE;	/* none, done with this function */
3394 	    }
3395 	}
3396 	/* error checking complete, do the decryption */
3397 	if ((rc == 0) && isEncrypt) {
3398 	    switch (session[encryptSession]->symmetric.algorithm) {
3399 	      case TPM_ALG_XOR:
3400 		rc = TSS_Response_EncryptXor(tssAuthContext, session[encryptSession]);
3401 		break;
3402 	      case TPM_ALG_AES:
3403 		rc = TSS_Response_EncryptAes(tssAuthContext, session[encryptSession]);
3404 		break;
3405 	      default:
3406 		if (tssVerbose) printf("TSS_Response_Encrypt: "
3407 				       "Error, algorithm %04x not implemented\n",
3408 				       session[encryptSession]->symmetric.algorithm);
3409 		rc = TSS_RC_BAD_ENCRYPT_ALGORITHM;
3410 		break;
3411 	    }
3412 	}
3413     }
3414 #else
3415     tssAuthContext = tssAuthContext;
3416     session = session;
3417     if ((rc == 0) && isEncrypt) {
3418 	if (tssVerbose)
3419 	    printf("TSS_Response_Encrypt: Error, with no crypto not implemented\n");
3420 	rc = TSS_RC_NOT_IMPLEMENTED;
3421     }
3422 #endif
3423     return rc;
3424 }
3425 
3426 #ifndef TPM_TSS_NOCRYPTO
3427 
3428 /* NOTE: if CFB also works, do in place decryption */
3429 
TSS_Response_EncryptXor(TSS_AUTH_CONTEXT * tssAuthContext,struct TSS_HMAC_CONTEXT * session)3430 static TPM_RC TSS_Response_EncryptXor(TSS_AUTH_CONTEXT *tssAuthContext,
3431 				      struct TSS_HMAC_CONTEXT *session)
3432 {
3433     TPM_RC		rc = 0;
3434     unsigned int	i;
3435     uint32_t 		paramSize;
3436     uint8_t 		*encryptParamBuffer;
3437     uint8_t 		*mask = NULL;
3438     uint8_t 		*decryptParamBuffer = NULL;
3439 
3440     /* get the TPM2B parameter to decrypt */
3441     if (rc == 0) {
3442 	rc = TSS_GetResponseEncryptParam(tssAuthContext,
3443 					 &paramSize, &encryptParamBuffer);
3444     }
3445     if (rc == 0) {
3446 	if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptXor: encrypt in",
3447 				      encryptParamBuffer, paramSize);
3448     }
3449     if (rc == 0) {
3450 	rc = TSS_Malloc(&mask, paramSize);			/* freed @1 */
3451     }
3452     if (rc == 0) {
3453 	rc = TSS_Malloc(&decryptParamBuffer, paramSize);	/* freed @2 */
3454     }
3455     /* generate the XOR pad */
3456     /* 21.2	XOR Parameter Obfuscation
3457 
3458        XOR(parameter, hashAlg, sessionValue, nonceNewer, nonceOlder)
3459 
3460        parameter	a variable sized buffer containing the parameter to be obfuscated
3461        hashAlg		the hash algorithm associated with the session
3462        sessionValue	the session-specific HMAC key
3463        nonceNewer	for commands, this will be nonceCaller and for responses it will be nonceTPM
3464        nonceOlder	for commands, this will be nonceTPM and for responses it will be nonceCaller
3465 
3466 
3467        11.4.6.3	XOR Obfuscation
3468 
3469        XOR(data, hashAlg, key, contextU, contextV)
3470 
3471        mask = KDFa (hashAlg, key, "XOR", contextU, contextV, data.size * 8)
3472     */
3473     /* KDFa for the XOR mask */
3474     if (rc == 0) {
3475 	if (tssVverbose) printf("TSS_Response_EncryptXor: hashAlg %04x\n", session->authHashAlg);
3476 	if (tssVverbose) printf("TSS_Response_EncryptXor: sizeInBits %04x\n", paramSize * 8);
3477 	if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptXor: session key",
3478 				      session->sessionKey.b.buffer, session->sessionKey.b.size);
3479 	rc = TSS_KDFA(mask,
3480 		      session->authHashAlg,
3481 		      &session->sessionValue.b,
3482 		      "XOR",
3483 		      &session->nonceTPM.b,
3484 		      &session->nonceCaller.b,
3485 		      paramSize * 8);
3486     }
3487     if (rc == 0) {
3488 	if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptXor: mask",
3489 				      mask, paramSize);
3490     }
3491     /* XOR */
3492     for (i = 0 ; (rc == 0) && (i < paramSize ) ; i++)  {
3493 	decryptParamBuffer[i] = encryptParamBuffer[i] ^ mask[i];
3494     }
3495     if (rc == 0) {
3496 	if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptXor: decrypt out",
3497 				      decryptParamBuffer, paramSize);
3498     }
3499     if (rc == 0) {
3500 	rc = TSS_SetResponseDecryptParam(tssAuthContext,
3501 					 paramSize, decryptParamBuffer);
3502     }
3503     free(mask);			/* @1 */
3504     free(decryptParamBuffer);	/* @2 */
3505     return rc;
3506 }
3507 
3508 #endif	/* TPM_TSS_NOCRYPTO */
3509 
3510 #ifndef TPM_TSS_NOCRYPTO
3511 
3512 /* NOTE: if CFB also works, do in place decryption */
3513 
TSS_Response_EncryptAes(TSS_AUTH_CONTEXT * tssAuthContext,struct TSS_HMAC_CONTEXT * session)3514 static TPM_RC TSS_Response_EncryptAes(TSS_AUTH_CONTEXT *tssAuthContext,
3515 				      struct TSS_HMAC_CONTEXT *session)
3516 {
3517     TPM_RC		rc = 0;
3518     uint32_t 		paramSize;
3519     uint8_t 		*encryptParamBuffer;
3520     uint8_t 		*decryptParamBuffer = NULL;
3521     TPM2B_IV		iv;
3522     uint32_t           	kdfaBits;
3523     uint16_t		keySizeinBytes;
3524     uint8_t		symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];	/* AES key + IV */
3525 
3526     /* get the TPM2B parameter to decrypt */
3527     if (rc == 0) {
3528 	rc = TSS_GetResponseEncryptParam(tssAuthContext,
3529 					 &paramSize, &encryptParamBuffer);
3530     }
3531     if (rc == 0) {
3532 	if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptAes: encrypt in",
3533 				      encryptParamBuffer, paramSize);
3534     }
3535     if (rc == 0) {
3536 	rc = TSS_Malloc(&decryptParamBuffer, paramSize);	/* freed @1 */
3537     }
3538     /* generate the encryption key and IV */
3539     /* 21.3	CFB Mode Parameter Encryption
3540 
3541        KDFa (hashAlg, sessionValue, "CFB", nonceNewer, nonceOlder, bits)	(34)
3542     */
3543     if (rc == 0) {
3544 
3545 	iv.t.size = TSS_Sym_GetBlockSize(session->symmetric.algorithm,
3546 					 session->symmetric.keyBits.aes);
3547 	/* generate random values for both the AES key and the IV */
3548 	kdfaBits = session->symmetric.keyBits.aes + (iv.t.size * 8);
3549 
3550 	if (tssVverbose) printf("TSS_Response_EncryptAes: hashAlg %04x\n",
3551 				session->authHashAlg);
3552 	if (tssVverbose) printf("TSS_Response_EncryptAes: AES key bits %u\n",
3553 				session->symmetric.keyBits.aes);
3554 	if (tssVverbose) printf("TSS_Response_EncryptAes: kdfaBits %04x\n",
3555 				kdfaBits);
3556 	if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptAes: session key",
3557 				      session->sessionKey.b.buffer, session->sessionKey.b.size);
3558 
3559 	rc = TSS_KDFA(&symParmString[0],
3560 		      session->authHashAlg,
3561 		      &session->sessionValue.b,
3562 		      "CFB",
3563 		      &session->nonceTPM.b,
3564 		      &session->nonceCaller.b,
3565 		      kdfaBits);
3566     }
3567     /* copy the latter part of the kdf output to the IV */
3568     if (rc == 0) {
3569 	keySizeinBytes = session->symmetric.keyBits.aes / 8;
3570 	memcpy(iv.t.buffer, &symParmString[keySizeinBytes], iv.t.size);
3571 	if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptAes: IV",
3572 				      iv.t.buffer, iv.t.size);
3573     }
3574     /* AES CFB decrypt the response */
3575     if (rc == 0) {
3576 	TPM_RC crc;
3577 	crc = TSS_AES_DecryptCFB(decryptParamBuffer,			/* output */
3578 				 session->symmetric.keyBits.aes,	/* 128 */
3579 				 symParmString,				/* key */
3580 				 iv.t.buffer,				/* IV */
3581 				 paramSize,				/* length */
3582 				 (uint8_t *)encryptParamBuffer);	/* input */
3583 	if (crc != 0) {
3584 	    if (tssVerbose) printf("TSS_Response_EncryptAes: AES decrypt failed\n");
3585 	    rc = TSS_RC_AES_DECRYPT_FAILURE;
3586 	}
3587     }
3588     if (rc == 0) {
3589 	if (tssVverbose) TSS_PrintAll("TSS_Response_EncryptAes: decrypt out",
3590 				      decryptParamBuffer, paramSize);
3591     }
3592     if (rc == 0) {
3593 	rc = TSS_SetResponseDecryptParam(tssAuthContext,
3594 					 paramSize, decryptParamBuffer);
3595     }
3596     free(decryptParamBuffer);	/* @1 */
3597     return rc;
3598 }
3599 
3600 #endif	/* TPM_TSS_NOCRYPTO */
3601 
3602 /*
3603   Command Change Authorization Processor
3604 */
3605 
3606 #ifndef TPM_TSS_NOCRYPTO
3607 
TSS_Command_ChangeAuthProcessor(TSS_CONTEXT * tssContext,struct TSS_HMAC_CONTEXT * session,size_t handleNumber,COMMAND_PARAMETERS * in)3608 static TPM_RC TSS_Command_ChangeAuthProcessor(TSS_CONTEXT *tssContext,
3609 					      struct TSS_HMAC_CONTEXT *session,
3610 					      size_t handleNumber,
3611 					      COMMAND_PARAMETERS *in)
3612 {
3613     TPM_RC 			rc = 0;
3614     size_t 			index;
3615     int 			found;
3616     TSS_ChangeAuthFunction_t 	changeAuthFunction = NULL;
3617 
3618     TPM_CC commandCode = TSS_GetCommandCode(tssContext->tssAuthContext);
3619 
3620     /* search the table for a change authorization processing function */
3621     if (rc == 0) {
3622 	found = FALSE;
3623 	for (index = 0 ; (index < (sizeof(tssTable) / sizeof(TSS_TABLE))) && !found ; index++) {
3624 	    if (tssTable[index].commandCode == commandCode) {
3625 		found = TRUE;
3626 		break;	/* don't increment index if found */
3627 	    }
3628 	}
3629     }
3630     /* found false means there is no change authorization function.  This permits the table to be
3631        smaller if desired. */
3632     if ((rc == 0) && found) {
3633 	changeAuthFunction = tssTable[index].changeAuthFunction;
3634 	/* there could also be an entry that is currently NULL, nothing to do */
3635 	if (changeAuthFunction == NULL) {
3636 	    found = FALSE;
3637 	}
3638     }
3639     /* call the processing function */
3640     if ((rc == 0) && found) {
3641 	rc = changeAuthFunction(tssContext, session, handleNumber, in);
3642     }
3643     return rc;
3644 }
3645 
3646 #endif	/* TPM_TSS_NOCRYPTO */
3647 
TSS_CA_HierarchyChangeAuth(TSS_CONTEXT * tssContext,struct TSS_HMAC_CONTEXT * session,size_t handleNumber,HierarchyChangeAuth_In * in)3648 static TPM_RC TSS_CA_HierarchyChangeAuth(TSS_CONTEXT *tssContext,
3649 					 struct TSS_HMAC_CONTEXT *session,
3650 					 size_t handleNumber,
3651 					 HierarchyChangeAuth_In *in)
3652 {
3653     TPM_RC 		rc = 0;
3654     char		*password = NULL;
3655 
3656     if (tssVverbose) printf("TSS_CA_HierarchyChangeAuth\n");
3657     if (in->newAuth.t.size == 0) {
3658 	password = NULL;
3659     }
3660     else {
3661 	if (rc == 0) {
3662 	    rc = TSS_Malloc((uint8_t **)&password,	/* freed @1 */
3663 			    in->newAuth.t.size + 1);
3664 	}
3665 	if (rc == 0) {
3666 	    /* copy the password */
3667 	    memcpy(password, in->newAuth.t.buffer, in->newAuth.t.size);
3668 	    password[in->newAuth.t.size] = '\0';	/* nul terminate string */
3669 	}
3670     }
3671 #ifndef TPM_TSS_NOCRYPTO
3672     if (rc == 0) {
3673 	rc = TSS_HmacSession_SetHmacKey(tssContext,
3674 					session,
3675 					handleNumber,
3676 					password);
3677     }
3678 #else
3679     tssContext = tssContext;
3680     session = session;
3681     handleNumber = handleNumber;
3682 #endif	/* TPM_TSS_NOCRYPTO */
3683     free(password);	/* @1 */
3684     return rc;
3685 }
3686 
TSS_CA_NV_ChangeAuth(TSS_CONTEXT * tssContext,struct TSS_HMAC_CONTEXT * session,size_t handleNumber,NV_ChangeAuth_In * in)3687 static TPM_RC TSS_CA_NV_ChangeAuth(TSS_CONTEXT *tssContext,
3688 				   struct TSS_HMAC_CONTEXT *session,
3689 				   size_t handleNumber,
3690 				   NV_ChangeAuth_In *in)
3691 {
3692     TPM_RC 		rc = 0;
3693     char		*password = NULL;
3694 
3695     if (tssVverbose) printf("TSS_CA_NV_ChangeAuth\n");
3696     if (in->newAuth.t.size == 0) {
3697 	password = NULL;
3698     }
3699     else {
3700 	if (rc == 0) {
3701 	    rc = TSS_Malloc((uint8_t **)&password,	/* freed @1 */
3702 			    in->newAuth.t.size + 1);
3703 	}
3704 	if (rc == 0) {
3705 	    /* copy the password */
3706 	    memcpy(password, in->newAuth.t.buffer, in->newAuth.t.size);
3707 	    password[in->newAuth.t.size] = '\0';	/* nul terminate string */
3708 	}
3709     }
3710 #ifndef TPM_TSS_NOCRYPTO
3711     if (rc == 0) {
3712 	rc = TSS_HmacSession_SetHmacKey(tssContext,
3713 					session,
3714 					handleNumber,
3715 					password);
3716     }
3717 #else
3718     tssContext = tssContext;
3719     session = session;
3720     handleNumber = handleNumber;
3721 #endif	/* TPM_TSS_NOCRYPTO */
3722     free(password);	/* @1 */
3723     return rc;
3724 }
3725 
TSS_CA_NV_UndefineSpaceSpecial(TSS_CONTEXT * tssContext,struct TSS_HMAC_CONTEXT * session,size_t handleNumber,NV_UndefineSpaceSpecial_In * in)3726 static TPM_RC TSS_CA_NV_UndefineSpaceSpecial(TSS_CONTEXT *tssContext,
3727 					     struct TSS_HMAC_CONTEXT *session,
3728 					     size_t handleNumber,
3729 					     NV_UndefineSpaceSpecial_In *in)
3730 {
3731     TPM_RC 		rc = 0;
3732 
3733     in = in;
3734     if (tssVverbose) printf("TSS_CA_NV_UndefineSpaceSpecial\n");
3735 #ifndef TPM_TSS_NOCRYPTO
3736     if (rc == 0) {
3737 	/* the nvIndex authorization, the zeroth authorization, has special handling */
3738 	if (handleNumber == 0) {
3739 	    /* the Empty Buffer is used as the authValue when generating the response HMAC */
3740 	    rc = TSS_HmacSession_SetHmacKey(tssContext,
3741 					    session,
3742 					    handleNumber,
3743 					    NULL);		/* password */
3744 	}
3745     }
3746 #else
3747     tssContext = tssContext;
3748     session = session;
3749     handleNumber = handleNumber;
3750 #endif	/* TPM_TSS_NOCRYPTO */
3751     return rc;
3752 }
3753 
3754 /*
3755   Command Pre-Processor
3756 */
3757 
TSS_Command_PreProcessor(TSS_CONTEXT * tssContext,TPM_CC commandCode,COMMAND_PARAMETERS * in,EXTRA_PARAMETERS * extra)3758 static TPM_RC TSS_Command_PreProcessor(TSS_CONTEXT *tssContext,
3759 				       TPM_CC commandCode,
3760 				       COMMAND_PARAMETERS *in,
3761 				       EXTRA_PARAMETERS *extra)
3762 {
3763     TPM_RC 			rc = 0;
3764     size_t 			index;
3765     int 			found;
3766     TSS_PreProcessFunction_t 	preProcessFunction = NULL;
3767 
3768     /* search the table for a pre-processing function */
3769     if (rc == 0) {
3770 	found = FALSE;
3771 	for (index = 0 ; (index < (sizeof(tssTable) / sizeof(TSS_TABLE))) && !found ; index++) {
3772 	    if (tssTable[index].commandCode == commandCode) {
3773 		found = TRUE;
3774 		break;	/* don't increment index if found */
3775 	    }
3776 	}
3777     }
3778     /* found false means there is no pre-processing function.  This permits the table to be smaller
3779        if desired. */
3780     if ((rc == 0) && found) {
3781 	preProcessFunction = tssTable[index].preProcessFunction;
3782 	/* call the pre processing function if there is one */
3783 	if (preProcessFunction != NULL) {
3784 	    rc = preProcessFunction(tssContext, in, extra);
3785 	}
3786     }
3787 #ifndef TPM_TSS_NO_PRINT
3788     if ((rc == 0) && tssVverbose) {
3789 	found = FALSE;
3790 	for (index = 0 ;
3791 	     (index < (sizeof(tssPrintTable) / sizeof(TSS_PRINT_TABLE))) && !found ;
3792 	     index++) {
3793 	    if (tssPrintTable[index].commandCode == commandCode) {
3794 		found = TRUE;
3795 		break;	/* don't increment index if found */
3796 	    }
3797 	}
3798     }
3799     /* found false means there is no print function.  This permits the table to be smaller
3800        if desired. */
3801     if ((rc == 0) && tssVverbose && found) {
3802 	TSS_InPrintFunction_t inPrintFunction = tssPrintTable[index].inPrintFunction;
3803 	/* call the pre processing function if there is one */
3804 	if (inPrintFunction != NULL) {
3805 	    printf("TSS_Command_PreProcessor: Input parameters\n");
3806 	    inPrintFunction(in, 8);	/* hard code indent 8 */
3807 	}
3808     }
3809 #endif /* TPM_TSS_NO_PRINT */
3810     return rc;
3811 }
3812 
3813 /*
3814   Command specific pre processing functions
3815 */
3816 
3817 /* TSS_PR_StartAuthSession handles StartAuthSession pre processing.
3818 
3819    If the salt key in->tpmKey is not NULL and an RSA key, the preprocessor supplies the encrypted
3820    salt.  It passes the unencrypted salt to the post processor for session key processing.
3821 
3822    An input salt (encrypted or unencrypted) is ignored.
3823 
3824    Returns an error if the key is not an RSA key.
3825 */
3826 
TSS_PR_StartAuthSession(TSS_CONTEXT * tssContext,StartAuthSession_In * in,StartAuthSession_Extra * extra)3827 static TPM_RC TSS_PR_StartAuthSession(TSS_CONTEXT *tssContext,
3828 				      StartAuthSession_In *in,
3829 				      StartAuthSession_Extra *extra)
3830 {
3831     TPM_RC 			rc = 0;
3832 
3833     if (tssVverbose) printf("TSS_PR_StartAuthSession\n");
3834 
3835     /* if (tssVverbose) StartAuthSession_In_Print(in, 8); */
3836 
3837 #ifndef TPM_TSS_NOCRYPTO
3838     /* generate nonceCaller */
3839     if (rc == 0) {
3840 	/* the size is determined by the session hash algorithm */
3841 	in->nonceCaller.t.size = TSS_GetDigestSize(in->authHash);
3842 	if (in->nonceCaller.t.size == 0) {
3843 	    if (tssVerbose) printf("TSS_PR_StartAuthSession: hash algorithm %04x not implemented\n",
3844 				   in->authHash);
3845 	    rc = TSS_RC_BAD_HASH_ALGORITHM;
3846 	}
3847     }
3848     if (rc == 0) {
3849 	rc = TSS_RandBytes((unsigned char *)&in->nonceCaller.t.buffer, in->nonceCaller.t.size);
3850     }
3851 #else
3852     in->nonceCaller.t.size = 16;
3853     memset(&in->nonceCaller.t.buffer, 0, 16);
3854 #endif	/* TPM_TSS_NOCRYPTO */
3855 	/* initialize to handle unsalted session */
3856     in->encryptedSalt.t.size = 0;
3857     if (extra != NULL) {		/* extra NULL is handled at the port processor */
3858 	extra->salt.t.size = 0;
3859     }
3860     /* if the caller requests a salted session */
3861     if (in->tpmKey != TPM_RH_NULL) {
3862 #ifndef TPM_TSS_NOCRYPTO
3863 	TPM2B_PUBLIC		bPublic;
3864 
3865 	if (rc == 0) {
3866 	    if (extra == NULL) {
3867 		if (tssVerbose)
3868 		    printf("TSS_PR_StartAuthSession: salt session requires extra parameter\n");
3869 		rc = TSS_RC_NULL_PARAMETER;
3870 	    }
3871 	}
3872 	/* get the tpmKey public key */
3873 	if (rc == 0) {
3874 	    rc = TSS_Public_Load(tssContext, &bPublic, in->tpmKey, NULL);
3875 	}
3876 	/* generate the salt and encrypted salt based on the asymmetric key type */
3877 	if (rc == 0) {
3878 	    switch (bPublic.publicArea.type) {
3879 #ifndef TPM_TSS_NOECC
3880 	      case TPM_ALG_ECC:
3881 		rc = TSS_ECC_Salt(&extra->salt,
3882 				  &in->encryptedSalt,
3883 				  &bPublic.publicArea);
3884 		break;
3885 #endif	/* TPM_TSS_NOECC */
3886 #ifndef TPM_TSS_NORSA
3887 	      case TPM_ALG_RSA:
3888 		rc = TSS_RSA_Salt(&extra->salt,
3889 				  &in->encryptedSalt,
3890 				  &bPublic.publicArea);
3891 		break;
3892 #endif 	/* TPM_TSS_NORSA */
3893 	      default:
3894 		if (tssVerbose)
3895 		    printf("TSS_PR_StartAuthSession: public key type %04x not supported\n",
3896 			   bPublic.publicArea.type);
3897 		rc = TSS_RC_BAD_SALT_KEY;
3898 	    }
3899 	}
3900 #else
3901 	tssContext = tssContext;
3902 	rc = TSS_RC_NOT_IMPLEMENTED;
3903 #endif	/* TPM_TSS_NOCRYPTO */
3904     }
3905     return rc;
3906 }
3907 
3908 #ifndef TPM_TSS_NOCRYPTO
3909 #ifndef TPM_TSS_NORSA
3910 
3911 /* TSS_RSA_Salt() returns both the plaintext and excrypted salt, based on the salt key bPublic. */
3912 
TSS_RSA_Salt(TPM2B_DIGEST * salt,TPM2B_ENCRYPTED_SECRET * encryptedSalt,TPMT_PUBLIC * publicArea)3913 static TPM_RC TSS_RSA_Salt(TPM2B_DIGEST 		*salt,
3914 			   TPM2B_ENCRYPTED_SECRET	*encryptedSalt,
3915 			   TPMT_PUBLIC			*publicArea)
3916 {
3917     TPM_RC		rc = 0;
3918 
3919     if (rc == 0) {
3920 	{
3921 	    /* error conditions when true */
3922 	    int b1 = publicArea->type != TPM_ALG_RSA;
3923 	    int b2 = publicArea->objectAttributes.val & TPMA_OBJECT_SIGN;
3924 	    int b3 = !(publicArea->objectAttributes.val & TPMA_OBJECT_DECRYPT);
3925 	    int b4 = (publicArea->parameters.rsaDetail.exponent != 0) &&
3926 		     /* some HW TPMs return 010001 for the RSA EK with the default IWG template */
3927 		     (publicArea->parameters.rsaDetail.exponent != RSA_DEFAULT_PUBLIC_EXPONENT);
3928 	    /* TSS support checks */
3929 	    if (b1 || b2 || b3 || b4) {
3930 		if (tssVerbose)
3931 		    printf("TSS_RSA_Salt: public key attributes not supported\n");
3932 		rc = TSS_RC_BAD_SALT_KEY;
3933 	    }
3934 	}
3935     }
3936     if (rc == 0) {
3937 	if (tssVverbose) TSS_PrintAll("TSS_RSA_Salt: public key",
3938 				      publicArea->unique.rsa.t.buffer,
3939 				      publicArea->unique.rsa.t.size);
3940     }
3941     /* generate a salt */
3942     if (rc == 0) {
3943 	/* The size of the secret value is limited to the size of the digest produced by the
3944 	   nameAlg of the object that is associated with the public key used for OAEP
3945 	   encryption. */
3946 	salt->t.size = TSS_GetDigestSize(publicArea->nameAlg);
3947 	if (tssVverbose) printf("TSS_RSA_Salt: "
3948 				"Hash algorithm %04x Salt size %u\n",
3949 				publicArea->nameAlg, salt->t.size);
3950 	/* place the salt in extra so that it can be retrieved by post processor */
3951 	rc = TSS_RandBytes((uint8_t *)&salt->t.buffer, salt->t.size);
3952     }
3953     /* In TPM2_StartAuthSession(), when tpmKey is an RSA key, the secret value (salt) is
3954        encrypted using OAEP as described in B.4. The string "SECRET" (see 4.5) is used as
3955        the L value and the nameAlg of the encrypting key is used for the hash algorithm. The
3956        data value in OAEP-encrypted blob (salt) is used to compute sessionKey. */
3957     if (rc == 0) {
3958 	if (tssVverbose) TSS_PrintAll("TSS_RSA_Salt: salt",
3959 				      (uint8_t *)&salt->t.buffer,
3960 				      salt->t.size);
3961     }
3962     /* encrypt the salt */
3963     if (rc == 0) {
3964 	/* public exponent */
3965 	unsigned char earr[3] = {0x01, 0x00, 0x01};
3966 	/* encrypt the salt with the tpmKey public key */
3967 	rc = TSS_RSAPublicEncrypt((uint8_t *)&encryptedSalt->t.secret,   /* encrypted data */
3968 				  publicArea->unique.rsa.t.size,  /* size of encrypted data buffer */
3969 				  (uint8_t *)&salt->t.buffer, /* decrypted data */
3970 				  salt->t.size,
3971 				  publicArea->unique.rsa.t.buffer,  /* public modulus */
3972 				  publicArea->unique.rsa.t.size,
3973 				  earr, 		/* public exponent */
3974 				  sizeof(earr),
3975 				  (unsigned char *)"SECRET",	/* encoding parameter */
3976 				  sizeof("SECRET"),
3977 				  publicArea->nameAlg);
3978     }
3979     if (rc == 0) {
3980 	encryptedSalt->t.size = publicArea->unique.rsa.t.size;
3981 	if (tssVverbose) TSS_PrintAll("TSS_RSA_Salt: RSA encrypted salt",
3982 				      encryptedSalt->t.secret,
3983 				      encryptedSalt->t.size);
3984     }
3985     return rc;
3986 }
3987 
3988 #endif /* TPM_TSS_NORSA */
3989 #endif /* TPM_TSS_NOCRYPTO */
3990 
TSS_PR_NV_DefineSpace(TSS_CONTEXT * tssContext,NV_DefineSpace_In * in,void * extra)3991 static TPM_RC TSS_PR_NV_DefineSpace(TSS_CONTEXT *tssContext,
3992 				    NV_DefineSpace_In *in,
3993 				    void *extra)
3994 {
3995     TPM_RC 	rc = 0;
3996     tssContext = tssContext;
3997     extra = extra;
3998 
3999     if (tssVverbose) printf("TSS_PR_NV_DefineSpace\n");
4000     /* Test that TPMA_NVA_POLICY_DELETE is only set when a policy is also set.  Otherwise, the index
4001        cannot ever be deleted, even with Platform Authorization. If the application really wants to
4002        do this, set the policy to one that cannot be satisfied, e.g., all 0xff's. */
4003     if (rc == 0) {
4004 	if (in->publicInfo.nvPublic.attributes.val & TPMA_NVA_POLICY_DELETE) {
4005 	    if (in->publicInfo.nvPublic.authPolicy.b.size == 0) {
4006 		if (tssVverbose) printf("TSS_PR_NV_DefineSpace POLICY_DELETE requires a policy\n");
4007 		rc = TSS_RC_IN_PARAMETER;
4008 	    }
4009 	}
4010     }
4011     return rc;
4012 }
4013 
4014 /*
4015   Response Post Processor
4016 */
4017 
4018 /* TSS_Response_PostProcessor() handles any response specific post processing
4019  */
4020 
TSS_Response_PostProcessor(TSS_CONTEXT * tssContext,COMMAND_PARAMETERS * in,RESPONSE_PARAMETERS * out,EXTRA_PARAMETERS * extra)4021 static TPM_RC TSS_Response_PostProcessor(TSS_CONTEXT *tssContext,
4022 					 COMMAND_PARAMETERS *in,
4023 					 RESPONSE_PARAMETERS *out,
4024 					 EXTRA_PARAMETERS *extra)
4025 {
4026     TPM_RC 			rc = 0;
4027     size_t 			index;
4028     int 			found;
4029     TSS_PostProcessFunction_t 	postProcessFunction = NULL;
4030 
4031     /* search the table for a post processing function */
4032     if (rc == 0) {
4033 	TPM_CC commandCode = TSS_GetCommandCode(tssContext->tssAuthContext);
4034 	found = FALSE;
4035 	for (index = 0 ; (index < (sizeof(tssTable) / sizeof(TSS_TABLE))) && !found ; index++) {
4036 	    if (tssTable[index].commandCode == commandCode) {
4037 		found = TRUE;
4038 		break;	/* don't increment index if found */
4039 	    }
4040 	}
4041     }
4042     /* found false means there is no post processing function.  This permits the table to be smaller
4043        if desired. */
4044     if ((rc == 0) && found) {
4045 	postProcessFunction = tssTable[index].postProcessFunction;
4046 	/* there could also be an entry that it currently NULL, nothing to do */
4047 	if (postProcessFunction == NULL) {
4048 	    found = FALSE;
4049 	}
4050     }
4051     /* call the function */
4052     if ((rc == 0) && found) {
4053 	rc = postProcessFunction(tssContext, in, out, extra);
4054     }
4055     return rc;
4056 }
4057 
4058 /*
4059   Command specific post processing functions
4060 */
4061 
4062 /* TSS_PO_StartAuthSession handles StartAuthSession post processing.  It:
4063 
4064    creates a TSS HMAC session
4065 
4066    saves the session handle, hash algorithm, and symmetric algorithm, nonceCaller and nonceTPM
4067 
4068    It calculates the session key and saves it
4069 
4070    Finally, it marshals the session and stores it
4071 */
4072 
TSS_PO_StartAuthSession(TSS_CONTEXT * tssContext,StartAuthSession_In * in,StartAuthSession_Out * out,StartAuthSession_Extra * extra)4073 static TPM_RC TSS_PO_StartAuthSession(TSS_CONTEXT *tssContext,
4074 				      StartAuthSession_In *in,
4075 				      StartAuthSession_Out *out,
4076 				      StartAuthSession_Extra *extra)
4077 {
4078     TPM_RC 			rc = 0;
4079     struct TSS_HMAC_CONTEXT 	*session = NULL;
4080     TPM2B_DIGEST 		salt;
4081 
4082     if (tssVverbose) printf("TSS_PO_StartAuthSession\n");
4083     /* allocate a TSS_HMAC_CONTEXT session context */
4084     if (rc == 0) {
4085 	rc = TSS_HmacSession_GetContext(&session);
4086     }
4087     if (rc == 0) {
4088 	session->sessionHandle = out->sessionHandle;
4089 	session->authHashAlg = in->authHash;
4090 #ifndef TPM_TSS_NOCRYPTO
4091 	session->sizeInBytes = TSS_GetDigestSize(session->authHashAlg);
4092 #endif
4093 	session->symmetric = in->symmetric;
4094 	session->sessionType = in->sessionType;
4095     }
4096     /* if not a bind session or if no bind password was supplied */
4097     if (rc == 0) {
4098 	if ((extra == NULL) || (in->bind == TPM_RH_NULL) || (extra->bindPassword == NULL)) {
4099 	    session->bindAuthValue.b.size = 0;
4100 	}
4101 	else {
4102 	    rc = TSS_TPM2B_StringCopy(&session->bindAuthValue.b,
4103 				      extra->bindPassword, sizeof(session->bindAuthValue.t.buffer));
4104 	}
4105     }
4106     if (rc == 0) {
4107 	/* if the caller did not supply extra, the salt must be empty */
4108 	if (extra == NULL) {
4109 	    salt.b.size = 0;
4110 	}
4111 	/* if the caller supplied extra, the preprocessor sets salt to empty (unsalted) or the
4112 	   plaintext salt value */
4113 	else {
4114 	    rc = TSS_TPM2B_Copy(&salt.b, &extra->salt.b, sizeof(TPMT_HA));
4115 	}
4116     }
4117 #ifndef TPM_TSS_NOCRYPTO
4118     if (rc == 0) {
4119 	rc = TSS_TPM2B_Copy(&session->nonceTPM.b, &out->nonceTPM.b, sizeof(TPMT_HA));
4120     }
4121     if (rc == 0) {
4122 	rc = TSS_TPM2B_Copy(&session->nonceCaller.b, &in->nonceCaller.b, sizeof(TPMT_HA));
4123     }
4124     if (rc == 0) {
4125 	rc = TSS_HmacSession_SetSessionKey(tssContext, session,
4126 					   &salt,
4127 					   in->bind, &session->bindAuthValue);
4128     }
4129 #endif	/* TPM_TSS_NOCRYPTO */
4130     if (rc == 0) {
4131 	rc = TSS_HmacSession_SaveSession(tssContext, session);
4132     }
4133     TSS_HmacSession_FreeContext(session);
4134     return rc;
4135 }
4136 
4137 /* TSS_PO_ContextSave() saves the name of an object in a filename that is a hash of the contextBlob.
4138 
4139    This permits the name to be found during ContextLoad.
4140 */
4141 
TSS_PO_ContextSave(TSS_CONTEXT * tssContext,ContextSave_In * in,ContextSave_Out * out,void * extra)4142 static TPM_RC TSS_PO_ContextSave(TSS_CONTEXT *tssContext,
4143 				 ContextSave_In *in,
4144 				 ContextSave_Out *out,
4145 				 void *extra)
4146 {
4147     TPM_RC 		rc = 0;
4148 #ifndef TPM_TSS_NOFILE
4149     TPMT_HA 		cpHash;		/* largest size of a digest */
4150     char		string[65];	/*  sha256 hash * 2 + 1 */
4151     TPM_HT 		handleType;
4152     int			done = FALSE;
4153 #endif
4154 
4155     in = in;
4156     extra = extra;
4157 
4158 #ifndef TPM_TSS_NOFILE
4159     if (tssVverbose) printf("TSS_PO_ContextSave: handle %08x\n", in->saveHandle);
4160     /* only for objects and sequence objects, not sessions */
4161     if (rc == 0) {
4162 	handleType = (TPM_HT) ((in->saveHandle & HR_RANGE_MASK) >> HR_SHIFT);
4163 	if (handleType != TPM_HT_TRANSIENT) {
4164 	    done = TRUE;
4165 	}
4166     }
4167     if ((rc == 0) && !done) {
4168 	cpHash.hashAlg = TPM_ALG_SHA256;	/* arbitrary choice */
4169 	rc = TSS_Hash_Generate(&cpHash,
4170 			       out->context.contextBlob.b.size, out->context.contextBlob.b.buffer,
4171 			       0, NULL);
4172     }
4173     /* convert a hash of the context blob to a string */
4174     if ((rc == 0) && !done) {
4175 	rc = TSS_HashToString(string, cpHash.digest.sha256);
4176     }
4177     if ((rc == 0) && !done) {
4178 	rc = TSS_Name_Copy(tssContext,
4179 			   0, string,			/* to context */
4180 			   in->saveHandle, NULL);	/* from handle */
4181     }
4182     /* get the public key of the object being context saved */
4183     /* save the public key under the context */
4184     if ((rc == 0) && !done) {
4185 	rc = TSS_Public_Copy(tssContext,
4186 			     0,
4187 			     string,
4188 			     in->saveHandle,
4189 			     NULL);
4190     }
4191 #else
4192     tssContext = tssContext;
4193     out = out;
4194 #endif
4195     return rc;
4196 }
4197 
TSS_PO_ContextLoad(TSS_CONTEXT * tssContext,ContextLoad_In * in,ContextLoad_Out * out,void * extra)4198 static TPM_RC TSS_PO_ContextLoad(TSS_CONTEXT *tssContext,
4199 				 ContextLoad_In *in,
4200 				 ContextLoad_Out *out,
4201 				 void *extra)
4202 {
4203     TPM_RC 		rc = 0;
4204 #ifndef TPM_TSS_NOFILE
4205     TPMT_HA 		cpHash;		/* largest size of a digest */
4206     char		string[65];	/*  sha256 hash * 2 + 1 */
4207     TPM_HT 		handleType;
4208     int			done = FALSE;
4209 #endif
4210 
4211     out = out;
4212     extra = extra;
4213 
4214 #ifndef TPM_TSS_NOFILE
4215     if (tssVverbose) printf("TSS_PO_ContextLoad: handle %08x\n", out->loadedHandle);
4216     /* only for objects and sequence objects, not sessions */
4217     if (rc == 0) {
4218 	handleType = (TPM_HT) ((out->loadedHandle & HR_RANGE_MASK) >> HR_SHIFT);
4219 	if (handleType != TPM_HT_TRANSIENT) {
4220 	    done = TRUE;
4221 	}
4222     }
4223     if ((rc == 0) && !done) {
4224 	cpHash.hashAlg = TPM_ALG_SHA256;	/* arbitrary choice */
4225 	rc = TSS_Hash_Generate(&cpHash,
4226 			       in->context.contextBlob.b.size, in->context.contextBlob.b.buffer,
4227 			       0, NULL);
4228     }
4229     /* convert a hash of the context blob to a string */
4230     if ((rc == 0) && !done) {
4231 	rc = TSS_HashToString(string, cpHash.digest.sha256);
4232     }
4233     /* get the Name of the object being context loaded */
4234     /* write the name with the loaded context's handle */
4235     if ((rc == 0) && !done) {
4236 	rc = TSS_Name_Copy(tssContext,
4237 			   out->loadedHandle, NULL,	/* to handle */
4238 			   0, string);			/* from context */
4239     }
4240     /* get the public key of the object being context loaded */
4241     /* write the public key with the loaded context's handle */
4242     if ((rc == 0) && !done) {
4243 	rc = TSS_Public_Copy(tssContext,
4244 			     out->loadedHandle,
4245 			     NULL,
4246 			     0,
4247 			     string);
4248     }
4249 #else
4250     tssContext = tssContext;
4251     in = in;
4252 #endif
4253     return rc;
4254 }
4255 
4256 /* TSS_HashToString() converts a SHA-256 binary hash (really any 32-byte value) to a string
4257 
4258    string must be 65 bytes: 32*2 + 1
4259 
4260    NOTE: Hard coded to SHA256
4261 */
4262 
4263 #ifndef TPM_TSS_NOFILE
4264 
TSS_HashToString(char * str,uint8_t * digest)4265 static TPM_RC TSS_HashToString(char *str, uint8_t *digest)
4266 {
4267     size_t i;
4268 
4269     for (i = 0 ; i < SHA256_DIGEST_SIZE ; i++) {
4270 	sprintf(str +(i*2), "%02x", digest[i]);
4271     }
4272     if (tssVverbose) printf("TSS_HashToString: %s\n", str);
4273     return 0;
4274 }
4275 
4276 #endif
4277 
4278 /* TSS_PO_FlushContext() removes persistent state associated with the handle */
4279 
TSS_PO_FlushContext(TSS_CONTEXT * tssContext,FlushContext_In * in,void * out,void * extra)4280 static TPM_RC TSS_PO_FlushContext(TSS_CONTEXT *tssContext,
4281 				  FlushContext_In *in,
4282 				  void *out,
4283 				  void *extra)
4284 {
4285     TPM_RC 			rc = 0;
4286 
4287     out = out;
4288     extra = extra;
4289     if (tssVverbose) printf("TSS_PO_FlushContext: flushHandle %08x\n", in->flushHandle);
4290     if (rc == 0) {
4291 	rc = TSS_DeleteHandle(tssContext, in->flushHandle);
4292     }
4293     return rc;
4294 }
4295 
4296 /* TSS_PO_EvictControl() removes persistent state associated with the handle */
4297 
TSS_PO_EvictControl(TSS_CONTEXT * tssContext,EvictControl_In * in,void * out,void * extra)4298 static TPM_RC TSS_PO_EvictControl(TSS_CONTEXT *tssContext,
4299 				  EvictControl_In *in,
4300 				  void *out,
4301 				  void *extra)
4302 {
4303     TPM_RC 			rc = 0;
4304 
4305     out = out;
4306     extra = extra;
4307 
4308     if (tssVverbose) printf("TSS_PO_EvictControl: object %08x persistent %08x\n",
4309 			    in->objectHandle, in->persistentHandle);
4310     /* if it successfully made a persistent copy */
4311     if (in->objectHandle != in->persistentHandle) {
4312 	/* TPM2B_PUBLIC	bPublic; */
4313 	if (rc == 0) {
4314 	    rc = TSS_Name_Copy(tssContext,
4315 			       in->persistentHandle, NULL,	/* to persistent handle */
4316 			       in->objectHandle, NULL);		/* from transient handle */
4317 	}
4318 	/* get the transient object public key */
4319 	/* copy it to the persistent object public key */
4320 	if (rc == 0) {
4321 	    rc = TSS_Public_Copy(tssContext,
4322 				 in->persistentHandle,
4323 				 NULL,
4324 				 in->objectHandle,
4325 				 NULL);
4326 	}
4327     }
4328     /* if it successfully evicted the persistent object */
4329     else {
4330 	if (rc == 0) {
4331 	    rc = TSS_DeleteHandle(tssContext, in->persistentHandle);
4332 	}
4333     }
4334     return rc;
4335 }
4336 
4337 /* TSS_PO_Load() saves the Name returned for the loaded object.  It saves the TPM2B_PUBLIC */
4338 
TSS_PO_Load(TSS_CONTEXT * tssContext,Load_In * in,Load_Out * out,void * extra)4339 static TPM_RC TSS_PO_Load(TSS_CONTEXT *tssContext,
4340 			  Load_In *in,
4341 			  Load_Out *out,
4342 			  void *extra)
4343 {
4344     TPM_RC 	rc = 0;
4345 
4346     in = in;
4347     extra = extra;
4348     if (tssVverbose) printf("TSS_PO_Load: handle %08x\n", out->objectHandle);
4349     /* use handle as file name */
4350     if (rc == 0) {
4351 	rc = TSS_Name_Store(tssContext, &out->name, out->objectHandle, NULL);
4352     }
4353     if (rc == 0) {
4354 	rc = TSS_Public_Store(tssContext, &in->inPublic, out->objectHandle, NULL);
4355     }
4356     return rc;
4357 }
4358 
4359 /* TSS_PO_LoadExternal() saves the Name returned for the loaded object */
4360 
TSS_PO_LoadExternal(TSS_CONTEXT * tssContext,LoadExternal_In * in,LoadExternal_Out * out,void * extra)4361 static TPM_RC TSS_PO_LoadExternal(TSS_CONTEXT *tssContext,
4362 				  LoadExternal_In *in,
4363 				  LoadExternal_Out *out,
4364 				  void *extra)
4365 {
4366     TPM_RC 	rc = 0;
4367 
4368     in = in;
4369     extra = extra;
4370     if (tssVverbose) printf("TSS_PO_LoadExternal: handle %08x\n", out->objectHandle);
4371     /* use handle as file name */
4372     if (rc == 0) {
4373 	rc = TSS_Name_Store(tssContext, &out->name, out->objectHandle, NULL);
4374     }
4375     if (rc == 0) {
4376 	rc = TSS_Public_Store(tssContext, &in->inPublic, out->objectHandle, NULL);
4377     }
4378     return rc;
4379 }
4380 
4381 /* TSS_PO_ReadPublic() saves the Name returned for the loaded object */
4382 
TSS_PO_ReadPublic(TSS_CONTEXT * tssContext,ReadPublic_In * in,ReadPublic_Out * out,void * extra)4383 static TPM_RC TSS_PO_ReadPublic(TSS_CONTEXT *tssContext,
4384 				ReadPublic_In *in,
4385 				ReadPublic_Out *out,
4386 				void *extra)
4387 {
4388     TPM_RC 	rc = 0;
4389 
4390     in = in;
4391     extra = extra;
4392     if (tssVverbose) printf("TSS_PO_ReadPublic: handle %08x\n", in->objectHandle);
4393     /* if the TSS is compiled without crypto support, it cannot recalculate the Name from the public
4394        area. It has to trust the response from the TPM.  This should be OK since a 'no crypto' TSS
4395        is used when there is a tructed path to the TPM. */
4396 #ifndef TPM_TSS_NOCRYPTO
4397     /* validate the Name against the public area */
4398     /* Name = nameAlg || HnameAlg (handle->publicArea)
4399        where
4400        nameAlg	algorithm used to compute Name
4401        HnameAlg	hash using the nameAlg parameter in the object associated with handle
4402        publicArea 	contents of the TPMT_PUBLIC associated with handle
4403     */
4404     {
4405 	TPM2B_NAME name;
4406 	if (rc == 0) {
4407 	    rc = TSS_ObjectPublic_GetName(&name, &out->outPublic.publicArea);
4408 	}
4409 	if (rc == 0) {
4410 	    if (name.t.size != out->name.t.size) {
4411 		if (tssVerbose)
4412 		    printf("TSS_PO_ReadPublic: TPMT_PUBLIC does not match TPM2B_NAME\n");
4413 		rc = TSS_RC_MALFORMED_PUBLIC;
4414 	    }
4415 	    else {
4416 		int irc;
4417 		irc = memcmp(name.t.name, out->name.t.name, out->name.t.size);
4418 		if (irc != 0) {
4419 		    if (tssVerbose)
4420 			printf("TSS_PO_ReadPublic: TPMT_PUBLIC does not match TPM2B_NAME\n");
4421 		    rc = TSS_RC_MALFORMED_PUBLIC;
4422 		}
4423 	    }
4424 	}
4425     }
4426 #endif
4427     /* use handle as file name */
4428     if (rc == 0) {
4429 	rc = TSS_Name_Store(tssContext, &out->name, in->objectHandle, NULL);
4430     }
4431     if (rc == 0) {
4432 	rc = TSS_Public_Store(tssContext, &out->outPublic, in->objectHandle, NULL);
4433     }
4434     return rc;
4435 }
4436 
4437 /* TSS_PO_Load() saves the Name returned for the loaded object.  It saves the TPM2B_PUBLIC */
4438 
TSS_PO_CreateLoaded(TSS_CONTEXT * tssContext,CreateLoaded_In * in,CreateLoaded_Out * out,void * extra)4439 static TPM_RC TSS_PO_CreateLoaded(TSS_CONTEXT *tssContext,
4440 				  CreateLoaded_In *in,
4441 				  CreateLoaded_Out *out,
4442 				  void *extra)
4443 {
4444     TPM_RC 	rc = 0;
4445 
4446     in = in;
4447     extra = extra;
4448     if (tssVverbose) printf("TSS_PO_CreateLoaded: handle %08x\n", out->objectHandle);
4449     /* use handle as file name */
4450     if (rc == 0) {
4451 	rc = TSS_Name_Store(tssContext, &out->name, out->objectHandle, NULL);
4452     }
4453     if (rc == 0) {
4454 	rc = TSS_Public_Store(tssContext, &out->outPublic, out->objectHandle, NULL);
4455     }
4456     return rc;
4457 }
4458 
4459 /* TSS_PO_HashSequenceStart() saves the Name returned for the started sequence object */
4460 
TSS_PO_HashSequenceStart(TSS_CONTEXT * tssContext,HashSequenceStart_In * in,HashSequenceStart_Out * out,void * extra)4461 static TPM_RC TSS_PO_HashSequenceStart(TSS_CONTEXT *tssContext,
4462 				       HashSequenceStart_In *in,
4463 				       HashSequenceStart_Out *out,
4464 				       void *extra)
4465 {
4466     TPM_RC 	rc = 0;
4467     TPM2B_NAME 	name;
4468 
4469     in = in;
4470     extra = extra;
4471 
4472     if (tssVverbose) printf("TSS_PO_HashSequenceStart\n");
4473     /* Part 1 Table 3 The Name of a sequence object is an Empty Buffer */
4474     if (rc == 0) {
4475 	name.b.size = 0;
4476 	/* use handle as file name */
4477 	rc = TSS_Name_Store(tssContext, &name, out->sequenceHandle, NULL);
4478     }
4479     return rc;
4480 }
4481 
4482 
4483 /* TSS_PO_HMAC_Start() saves the Name returned for the started sequence object */
4484 
TSS_PO_HMAC_Start(TSS_CONTEXT * tssContext,HMAC_Start_In * in,HMAC_Start_Out * out,void * extra)4485 static TPM_RC TSS_PO_HMAC_Start(TSS_CONTEXT *tssContext,
4486 				HMAC_Start_In *in,
4487 				HMAC_Start_Out *out,
4488 				void *extra)
4489 {
4490     TPM_RC 	rc = 0;
4491     TPM2B_NAME 	name;
4492 
4493     in = in;
4494     extra = extra;
4495 
4496     if (tssVverbose) printf("TSS_PO_HMAC_Start\n");
4497     /* Part 1 Table 3 The Name of a sequence object is an Empty Buffer */
4498     if (rc == 0) {
4499 	name.b.size = 0;
4500 	/* use handle as file name */
4501 	rc = TSS_Name_Store(tssContext, &name, out->sequenceHandle, NULL);
4502     }
4503     return rc;
4504 }
4505 
TSS_PO_SequenceComplete(TSS_CONTEXT * tssContext,SequenceComplete_In * in,SequenceComplete_Out * out,void * extra)4506 static TPM_RC TSS_PO_SequenceComplete(TSS_CONTEXT *tssContext,
4507 				      SequenceComplete_In *in,
4508 				      SequenceComplete_Out *out,
4509 				      void *extra)
4510 {
4511     TPM_RC 	rc = 0;
4512 
4513     out = out;
4514     extra = extra;
4515 
4516     if (tssVverbose) printf("TSS_PO_SequenceComplete: sequenceHandle %08x\n", in->sequenceHandle);
4517     if (rc == 0) {
4518 	rc = TSS_DeleteHandle(tssContext, in->sequenceHandle);
4519     }
4520     return rc;
4521 }
TSS_PO_EventSequenceComplete(TSS_CONTEXT * tssContext,EventSequenceComplete_In * in,EventSequenceComplete_Out * out,void * extra)4522 static TPM_RC TSS_PO_EventSequenceComplete(TSS_CONTEXT *tssContext,
4523 					   EventSequenceComplete_In *in,
4524 					   EventSequenceComplete_Out *out,
4525 					   void *extra)
4526 {
4527     TPM_RC 	rc = 0;
4528     out = out;
4529     extra = extra;
4530     if (tssVverbose)
4531 	printf("TSS_PO_EventSequenceComplete: sequenceHandle %08x\n", in->sequenceHandle);
4532     if (rc == 0) {
4533 	rc = TSS_DeleteHandle(tssContext, in->sequenceHandle);
4534     }
4535     return rc;
4536 }
4537 
TSS_PO_PolicyAuthValue(TSS_CONTEXT * tssContext,PolicyAuthValue_In * in,void * out,void * extra)4538 static TPM_RC TSS_PO_PolicyAuthValue(TSS_CONTEXT *tssContext,
4539 				     PolicyAuthValue_In *in,
4540 				     void *out,
4541 				     void *extra)
4542 {
4543     TPM_RC 			rc = 0;
4544     struct TSS_HMAC_CONTEXT 	*session = NULL;
4545 
4546     out = out;
4547     extra = extra;
4548     if (tssVverbose) printf("TSS_PO_PolicyAuthValue\n");
4549     if (rc == 0) {
4550 	rc = TSS_Malloc((unsigned char **)&session, sizeof(TSS_HMAC_CONTEXT));	/* freed @1 */
4551     }
4552     if (rc == 0) {
4553 	rc = TSS_HmacSession_LoadSession(tssContext, session, in->policySession);
4554     }
4555     if (rc == 0) {
4556 	session->isPasswordNeeded = FALSE;
4557 	session->isAuthValueNeeded = TRUE;
4558 	rc = TSS_HmacSession_SaveSession(tssContext, session);
4559     }
4560     free(session);		/* @1 */
4561     return rc;
4562 }
4563 
TSS_PO_PolicyPassword(TSS_CONTEXT * tssContext,PolicyPassword_In * in,void * out,void * extra)4564 static TPM_RC TSS_PO_PolicyPassword(TSS_CONTEXT *tssContext,
4565 				    PolicyPassword_In *in,
4566 				    void *out,
4567 				    void *extra)
4568 {
4569     TPM_RC 			rc = 0;
4570     struct TSS_HMAC_CONTEXT 	*session = NULL;
4571 
4572     out = out;
4573     extra = extra;
4574     if (tssVverbose) printf("TSS_PO_PolicyPassword\n");
4575     if (rc == 0) {
4576 	rc = TSS_Malloc((unsigned char **)&session, sizeof(TSS_HMAC_CONTEXT));	/* freed @1 */
4577     }
4578     if (rc == 0) {
4579 	rc = TSS_HmacSession_LoadSession(tssContext, session, in->policySession);
4580     }
4581     if (rc == 0) {
4582 	session->isPasswordNeeded = TRUE;
4583 	session->isAuthValueNeeded = FALSE;
4584 	rc = TSS_HmacSession_SaveSession(tssContext, session);
4585     }
4586     free(session);		/* @1 */
4587     return rc;
4588 }
4589 
TSS_PO_CreatePrimary(TSS_CONTEXT * tssContext,CreatePrimary_In * in,CreatePrimary_Out * out,void * extra)4590 static TPM_RC TSS_PO_CreatePrimary(TSS_CONTEXT *tssContext,
4591 				   CreatePrimary_In *in,
4592 				   CreatePrimary_Out *out,
4593 				   void *extra)
4594 {
4595     TPM_RC 			rc = 0;
4596 
4597     in = in;
4598     extra = extra;
4599     if (tssVverbose) printf("TSS_PO_CreatePrimary: handle %08x\n", out->objectHandle);
4600     /* use handle as file name */
4601     if (rc == 0) {
4602 	rc = TSS_Name_Store(tssContext, &out->name, out->objectHandle, NULL);
4603     }
4604     if (rc == 0) {
4605 	rc = TSS_Public_Store(tssContext, &out->outPublic, out->objectHandle, NULL);
4606     }
4607     return rc;
4608 }
4609 
TSS_PO_NV_DefineSpace(TSS_CONTEXT * tssContext,NV_DefineSpace_In * in,void * out,void * extra)4610 static TPM_RC TSS_PO_NV_DefineSpace(TSS_CONTEXT *tssContext,
4611 				    NV_DefineSpace_In *in,
4612 				    void *out,
4613 				    void *extra)
4614 {
4615     TPM_RC 	rc = 0;
4616 
4617     if (tssVverbose) printf("TSS_PO_NV_DefineSpace\n");
4618 #ifndef TPM_TSS_NOCRYPTO
4619     {
4620 	TPM2B_NAME name;
4621 	/* calculate the Name from the input public area */
4622 	/* Name = nameAlg || HnameAlg (handle->nvPublicArea)
4623 	   where
4624 	   nameAlg	algorithm used to compute Name
4625 	   HnameAlg hash using the nameAlg parameter in the NV Index location associated with handle
4626 	   nvPublicArea	contents of the TPMS_NV_PUBLIC associated with handle
4627 	*/
4628 	/* calculate the Name from the input TPMS_NV_PUBLIC */
4629 	if (rc == 0) {
4630 	    rc = TSS_NVPublic_GetName(&name, &in->publicInfo.nvPublic);
4631 	}
4632 	/* use handle as file name */
4633 	if (rc == 0) {
4634 	    rc = TSS_Name_Store(tssContext, &name, in->publicInfo.nvPublic.nvIndex, NULL);
4635 	}
4636 	if (rc == 0) {
4637 	    rc = TSS_NVPublic_Store(tssContext, &in->publicInfo.nvPublic,
4638 				    in->publicInfo.nvPublic.nvIndex);
4639 	}
4640     }
4641 #else
4642     tssContext = tssContext;
4643     in = in;
4644 #endif
4645     out = out;
4646     extra = extra;
4647     return rc;
4648 }
4649 
4650 
TSS_PO_NV_ReadPublic(TSS_CONTEXT * tssContext,NV_ReadPublic_In * in,NV_ReadPublic_Out * out,void * extra)4651 static TPM_RC TSS_PO_NV_ReadPublic(TSS_CONTEXT *tssContext,
4652 				   NV_ReadPublic_In *in,
4653 				   NV_ReadPublic_Out *out,
4654 				   void *extra)
4655 {
4656     TPM_RC 	rc = 0;
4657 
4658     if (tssVverbose) printf("TSS_PO_NV_ReadPublic\n");
4659 
4660     /* validate the Name against the public area */
4661     /* Name = nameAlg || HnameAlg (handle->nvPublicArea)
4662        where
4663        nameAlg	algorithm used to compute Name
4664        HnameAlg hash using the nameAlg parameter in the NV Index location associated with handle
4665        nvPublicArea	contents of the TPMS_NV_PUBLIC associated with handle
4666     */
4667 #ifndef TPM_TSS_NOCRYPTO
4668     {
4669 	TPM2B_NAME name;
4670 	/* calculate the Name from the TPMS_NV_PUBLIC */
4671 	if (rc == 0) {
4672 	    rc = TSS_NVPublic_GetName(&name, &out->nvPublic.nvPublic);
4673 	}
4674 	if (rc == 0) {
4675 	    if (name.t.size != out->nvName.t.size) {
4676 		if (tssVerbose)
4677 		    printf("TSS_PO_NV_ReadPublic: TPMT_NV_PUBLIC does not match TPM2B_NAME\n");
4678 		rc = TSS_RC_MALFORMED_NV_PUBLIC;
4679 	    }
4680 	    else {
4681 		int irc;
4682 		irc = memcmp(name.t.name, out->nvName.t.name, out->nvName.t.size);
4683 		if (irc != 0) {
4684 		    if (tssVerbose)
4685 			printf("TSS_PO_NV_ReadPublic: TPMT_NV_PUBLIC does not match TPM2B_NAME\n");
4686 		    rc = TSS_RC_MALFORMED_NV_PUBLIC;
4687 		}
4688 	    }
4689 	}
4690 	/* use handle as file name */
4691 	if (rc == 0) {
4692 	    rc = TSS_Name_Store(tssContext, &out->nvName, in->nvIndex, NULL);
4693 	}
4694 	if (rc == 0) {
4695 	    rc = TSS_NVPublic_Store(tssContext, &out->nvPublic.nvPublic, in->nvIndex);
4696 	}
4697     }
4698 #else
4699     tssContext = tssContext;
4700     in = in;
4701     out = out;
4702 #endif
4703     extra = extra;
4704     return rc;
4705 }
4706 
TSS_PO_NV_UndefineSpace(TSS_CONTEXT * tssContext,NV_UndefineSpace_In * in,void * out,void * extra)4707 static TPM_RC TSS_PO_NV_UndefineSpace(TSS_CONTEXT *tssContext,
4708 				      NV_UndefineSpace_In *in,
4709 				      void *out,
4710 				      void *extra)
4711 {
4712     TPM_RC 			rc = 0;
4713 
4714     out = out;
4715     extra = extra;
4716     if (tssVverbose) printf("TSS_PO_NV_UndefineSpace\n");
4717 #ifndef TPM_TSS_NOCRYPTO
4718     /* Don't check return code. */
4719     TSS_DeleteHandle(tssContext, in->nvIndex);
4720     TSS_NVPublic_Delete(tssContext, in->nvIndex);
4721 #else
4722     tssContext = tssContext;
4723     in = in;
4724 #endif
4725     return rc;
4726 }
4727 
TSS_PO_NV_UndefineSpaceSpecial(TSS_CONTEXT * tssContext,NV_UndefineSpaceSpecial_In * in,void * out,void * extra)4728 static TPM_RC TSS_PO_NV_UndefineSpaceSpecial(TSS_CONTEXT *tssContext,
4729 					     NV_UndefineSpaceSpecial_In *in,
4730 					     void *out,
4731 					     void *extra)
4732 {
4733     TPM_RC 			rc = 0;
4734 
4735     out = out;
4736     extra = extra;
4737     if (tssVverbose) printf("TSS_PO_NV_UndefineSpaceSpecial\n");
4738     /* Don't check return code.  The name will only exist if NV_ReadPublic has been issued */
4739     TSS_DeleteHandle(tssContext, in->nvIndex);
4740     TSS_NVPublic_Delete(tssContext, in->nvIndex);
4741     return rc;
4742 }
4743 
4744 /* TSS_PO_NV_Write() handles the Name and NVPublic update for the 4 NV write commands: write,
4745    increment, extend, and setbits */
4746 
TSS_PO_NV_Write(TSS_CONTEXT * tssContext,NV_Write_In * in,void * out,void * extra)4747 static TPM_RC TSS_PO_NV_Write(TSS_CONTEXT *tssContext,
4748 			      NV_Write_In *in,
4749 			      void *out,
4750 			      void *extra)
4751 {
4752     TPM_RC 			rc = 0;
4753 
4754     if (tssVverbose) printf("TSS_PO_NV_Write, Increment, Extend, SetBits:\n");
4755 
4756 #ifndef TPM_TSS_NOCRYPTO
4757     {
4758 	TPMS_NV_PUBLIC 		nvPublic;
4759 	TPM2B_NAME 		name;		/* new name */
4760 
4761 	if (rc == 0) {
4762 	    rc = TSS_NVPublic_Load(tssContext, &nvPublic, in->nvIndex);
4763 	}
4764 	/* if the previous store had written clear */
4765 	if (!(nvPublic.attributes.val & TPMA_NVA_WRITTEN)) {
4766 	    if (rc == 0) {
4767 		/* set the written bit */
4768 		nvPublic.attributes.val |= TPMA_NVA_WRITTEN;
4769 		/* save the TPMS_NV_PUBLIC */
4770 		rc = TSS_NVPublic_Store(tssContext, &nvPublic, in->nvIndex);
4771 	    }
4772 	    /* calculate the name */
4773 	    if (rc == 0) {
4774 		rc = TSS_NVPublic_GetName(&name, &nvPublic);
4775 	    }
4776 	    /* save the name */
4777 	    if (rc == 0) {
4778 		/* use handle as file name */
4779 		rc = TSS_Name_Store(tssContext, &name, in->nvIndex, NULL);
4780 	    }
4781 	    /* if there is a failure. delete the name and NVPublic */
4782 	    if (rc != 0) {
4783 		TSS_DeleteHandle(tssContext, in->nvIndex);
4784 		TSS_NVPublic_Delete(tssContext, in->nvIndex);
4785 	    }
4786 	}
4787     }
4788 #else
4789     tssContext = tssContext;
4790     in = in;
4791 #endif
4792     out = out;
4793     extra = extra;
4794     return rc;
4795 }
4796 
4797 /* TSS_PO_NV_WriteLock() handles the Name and NVPublic update for the write lock command */
4798 
TSS_PO_NV_WriteLock(TSS_CONTEXT * tssContext,NV_WriteLock_In * in,void * out,void * extra)4799 static TPM_RC TSS_PO_NV_WriteLock(TSS_CONTEXT *tssContext,
4800 				  NV_WriteLock_In *in,
4801 				  void *out,
4802 				  void *extra)
4803 {
4804     TPM_RC 			rc = 0;
4805 
4806     if (tssVverbose) printf("TSS_PO_NV_WriteLock:\n");
4807 
4808 #ifndef TPM_TSS_NOCRYPTO
4809     {
4810 	TPMS_NV_PUBLIC 		nvPublic;
4811 	TPM2B_NAME 		name;		/* new name */
4812 
4813  	if (rc == 0) {
4814 	    rc = TSS_NVPublic_Load(tssContext, &nvPublic, in->nvIndex);
4815 	}
4816 	/* if the previous store had write lock clear */
4817 	if (!(nvPublic.attributes.val & TPMA_NVA_WRITELOCKED)) {
4818 	    if (rc == 0) {
4819 		/* set the write lock bit */
4820 		nvPublic.attributes.val |= TPMA_NVA_WRITELOCKED;
4821 		/* save the TPMS_NV_PUBLIC */
4822 		rc = TSS_NVPublic_Store(tssContext, &nvPublic, in->nvIndex);
4823 	    }
4824 	    /* calculate the name */
4825 	    if (rc == 0) {
4826 		rc = TSS_NVPublic_GetName(&name, &nvPublic);
4827 	    }
4828 	    /* save the name */
4829 	    if (rc == 0) {
4830 		/* use handle as file name */
4831 		rc = TSS_Name_Store(tssContext, &name, in->nvIndex, NULL);
4832 	    }
4833 	    /* if there is a failure. delete the name and NVPublic */
4834 	    if (rc != 0) {
4835 		TSS_DeleteHandle(tssContext, in->nvIndex);
4836 		TSS_NVPublic_Delete(tssContext, in->nvIndex);
4837 	    }
4838 	}
4839     }
4840 #else
4841     tssContext = tssContext;
4842     in = in;
4843 #endif
4844     out = out;
4845     extra = extra;
4846     return rc;
4847 }
4848 
4849 /* TSS_PO_NV_WriteLock() handles the Name and NVPublic update for the read lock command */
4850 
TSS_PO_NV_ReadLock(TSS_CONTEXT * tssContext,NV_ReadLock_In * in,void * out,void * extra)4851 static TPM_RC TSS_PO_NV_ReadLock(TSS_CONTEXT *tssContext,
4852 				 NV_ReadLock_In *in,
4853 				 void *out,
4854 				 void *extra)
4855 {
4856     TPM_RC 			rc = 0;
4857 
4858     if (tssVverbose) printf("TSS_PO_NV_ReadLock:");
4859 
4860 #ifndef TPM_TSS_NOCRYPTO
4861     {
4862 	TPMS_NV_PUBLIC 		nvPublic;
4863 	TPM2B_NAME 			name;		/* new name */
4864 
4865 	if (rc == 0) {
4866 	    rc = TSS_NVPublic_Load(tssContext, &nvPublic, in->nvIndex);
4867 	}
4868 	/* if the previous store had read lock clear */
4869 	if (!(nvPublic.attributes.val & TPMA_NVA_READLOCKED)) {
4870 	    if (rc == 0) {
4871 		/* set the read lock bit */
4872 		nvPublic.attributes.val |= TPMA_NVA_READLOCKED;
4873 		/* save the TPMS_NV_PUBLIC */
4874 		rc = TSS_NVPublic_Store(tssContext, &nvPublic, in->nvIndex);
4875 	    }
4876 	    /* calculate the name */
4877 	    if (rc == 0) {
4878 		rc = TSS_NVPublic_GetName(&name, &nvPublic);
4879 	    }
4880 	    /* save the name */
4881 	    if (rc == 0) {
4882 		/* use handle as file name */
4883 		rc = TSS_Name_Store(tssContext, &name, in->nvIndex, NULL);
4884 	    }
4885 	    /* if there is a failure. delete the name and NVPublic */
4886 	    if (rc != 0) {
4887 		TSS_DeleteHandle(tssContext, in->nvIndex);
4888 		TSS_NVPublic_Delete(tssContext, in->nvIndex);
4889 	    }
4890 	}
4891     }
4892 #else
4893     tssContext = tssContext;
4894     in = in;
4895 #endif
4896     out = out;
4897     extra = extra;
4898     return rc;
4899 }
4900 
4901