1
2/*
3 * Licensed Materials - Property of IBM
4 *
5 * trousers - An open source TCG Software Stack
6 *
7 * (C) Copyright International Business Machines Corp. 2004-2007
8 *
9 */
10
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <string.h>
15#include <time.h>
16#include <errno.h>
17#include <assert.h>
18
19#include "trousers/tss.h"
20#include "trousers/trousers.h"
21#include "trousers_types.h"
22#include "tcs_tsp.h"
23#include "spi_utils.h"
24#include "capabilities.h"
25#include "tsplog.h"
26#include "obj.h"
27#include "authsess.h"
28
29
30TSS_RESULT
31secret_PerformAuth_OIAP(TSS_HOBJECT hAuthorizedObject,
32			UINT32 ulPendingFn,
33			TSS_HPOLICY hPolicy,
34			TSS_BOOL cas, /* continue auth session */
35			TCPA_DIGEST *hashDigest,
36			TPM_AUTH *auth)
37{
38	TSS_RESULT result;
39	TSS_BOOL bExpired;
40	UINT32 mode;
41	TCPA_SECRET secret;
42	TSS_HCONTEXT tspContext;
43	TSS_RESULT (*OIAP)(TSS_HCONTEXT, TCS_AUTHHANDLE *, TPM_NONCE *); // XXX hack
44	TSS_RESULT (*TerminateHandle)(TSS_HCONTEXT, TCS_HANDLE); // XXX hack
45
46	/* This validates that the secret can be used */
47	if ((result = obj_policy_has_expired(hPolicy, &bExpired)))
48		return result;
49
50	if (bExpired == TRUE)
51		return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
52
53	if ((result = obj_policy_get_tsp_context(hPolicy, &tspContext)))
54		return result;
55
56	if ((result = obj_policy_get_mode(hPolicy, &mode)))
57		return result;
58
59	if ((result = Init_AuthNonce(tspContext, cas, auth)))
60		return result;
61
62	/* XXX hack for opening a transport session */
63	if (cas) {
64		OIAP = RPC_OIAP;
65		TerminateHandle = RPC_TerminateHandle;
66	} else {
67		OIAP = TCS_API(tspContext)->OIAP;
68		TerminateHandle = TCS_API(tspContext)->TerminateHandle;
69	}
70
71	/* added retry logic */
72	if ((result = OIAP(tspContext, &auth->AuthHandle, &auth->NonceEven))) {
73		if (result == TCPA_E_RESOURCES) {
74			int retry = 0;
75			do {
76				/* POSIX sleep time, { secs, nanosecs } */
77				struct timespec t = { 0, AUTH_RETRY_NANOSECS };
78
79				nanosleep(&t, NULL);
80
81				result = OIAP(tspContext, &auth->AuthHandle, &auth->NonceEven);
82			} while (result == TCPA_E_RESOURCES && ++retry < AUTH_RETRY_COUNT);
83		}
84
85		if (result)
86			return result;
87	}
88
89	switch (mode) {
90		case TSS_SECRET_MODE_CALLBACK:
91			result = obj_policy_do_hmac(hPolicy, hAuthorizedObject,
92						    TRUE, ulPendingFn,
93						    auth->fContinueAuthSession,
94						    20,
95						    auth->NonceEven.nonce,
96						    auth->NonceOdd.nonce,
97						    NULL, NULL, 20,
98						    hashDigest->digest,
99						    (BYTE *)&auth->HMAC);
100			break;
101		case TSS_SECRET_MODE_SHA1:
102		case TSS_SECRET_MODE_PLAIN:
103		case TSS_SECRET_MODE_POPUP:
104			if ((result = obj_policy_get_secret(hPolicy, TR_SECRET_CTX_NOT_NEW,
105							    &secret)))
106				break;
107
108			HMAC_Auth(secret.authdata, hashDigest->digest, auth);
109			break;
110		case TSS_SECRET_MODE_NONE:
111			/* fall through */
112		default:
113			result = TSPERR(TSS_E_POLICY_NO_SECRET);
114			break;
115	}
116
117	if (result) {
118		TerminateHandle(tspContext, auth->AuthHandle);
119		return result;
120	}
121
122	return obj_policy_dec_counter(hPolicy);
123}
124#if 0
125TSS_RESULT
126secret_PerformXOR_OSAP(TSS_HPOLICY hPolicy, TSS_HPOLICY hUsagePolicy,
127		       TSS_HPOLICY hMigrationPolicy, TSS_HOBJECT hOSAPObject,
128		       UINT16 osapType, UINT32 osapData,
129		       TCPA_ENCAUTH * encAuthUsage, TCPA_ENCAUTH * encAuthMig,
130		       BYTE *sharedSecret, TPM_AUTH * auth, TCPA_NONCE * nonceEvenOSAP)
131{
132	TSS_BOOL bExpired;
133	TCPA_SECRET keySecret;
134	TCPA_SECRET usageSecret;
135	TCPA_SECRET migSecret = { { 0, } };
136	UINT32 keyMode, usageMode, migMode = 0;
137	TSS_RESULT result;
138	TSS_HCONTEXT tspContext;
139
140
141	if ((result = obj_policy_has_expired(hPolicy, &bExpired)))
142		return result;
143
144	if (bExpired == TRUE)
145		return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
146
147	if ((result = obj_policy_has_expired(hUsagePolicy, &bExpired)))
148		return result;
149
150	if (bExpired == TRUE)
151		return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
152
153	if (hMigrationPolicy) {
154		if ((result = obj_policy_has_expired(hMigrationPolicy, &bExpired)))
155			return result;
156
157		if (bExpired == TRUE)
158			return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
159
160		if ((result = obj_policy_get_mode(hMigrationPolicy, &migMode)))
161			return result;
162	}
163
164	if ((result = obj_policy_get_tsp_context(hPolicy, &tspContext)))
165		return result;
166
167	if ((result = obj_policy_get_mode(hPolicy, &keyMode)))
168		return result;
169
170	if ((result = obj_policy_get_mode(hUsagePolicy, &usageMode)))
171		return result;
172
173	if (keyMode == TSS_SECRET_MODE_CALLBACK ||
174	    usageMode == TSS_SECRET_MODE_CALLBACK ||
175	    (hMigrationPolicy && migMode == TSS_SECRET_MODE_CALLBACK)) {
176		if (keyMode != TSS_SECRET_MODE_CALLBACK ||
177		    usageMode != TSS_SECRET_MODE_CALLBACK ||
178		    (hMigrationPolicy && migMode != TSS_SECRET_MODE_CALLBACK))
179			return TSPERR(TSS_E_BAD_PARAMETER);
180	}
181
182	if (keyMode != TSS_SECRET_MODE_CALLBACK) {
183		if ((result = obj_policy_get_secret(hPolicy, TR_SECRET_CTX_NOT_NEW, &keySecret)))
184			return result;
185
186		if ((result = obj_policy_get_secret(hUsagePolicy, TR_SECRET_CTX_NEW, &usageSecret)))
187			return result;
188
189		if (hMigrationPolicy) {
190			if ((result = obj_policy_get_secret(hMigrationPolicy, TR_SECRET_CTX_NEW,
191							&migSecret)))
192				return result;
193		}
194
195		if ((result = OSAP_Calc(tspContext, osapType, osapData,
196					keySecret.authdata, usageSecret.authdata,
197					migSecret.authdata, encAuthUsage,
198					encAuthMig, sharedSecret, auth)))
199			return result;
200	} else {
201		/* If the secret mode is NONE here, we don't return an error. This is
202		 * because there are commands such as CreateKey, which require an auth
203		 * session even when creating no-auth keys. A secret of all 0's will be
204		 * used in this case. */
205		if ((result = TCS_API(tspContext)->OSAP(tspContext, osapType, osapData,
206							&auth->NonceOdd, &auth->AuthHandle,
207							&auth->NonceEven, nonceEvenOSAP)))
208			return result;
209
210		if ((result = obj_policy_do_xor(hPolicy, hOSAPObject,
211						hPolicy, TRUE, 20,
212						auth->NonceEven.nonce, NULL,
213						nonceEvenOSAP->nonce,
214						auth->NonceOdd.nonce, 20,
215						encAuthUsage->authdata,
216						encAuthMig->authdata))) {
217			TCS_API(tspContext)->TerminateHandle(tspContext, auth->AuthHandle);
218			return result;
219		}
220	}
221
222	return TSS_SUCCESS;
223}
224
225TSS_RESULT
226secret_PerformAuth_OSAP(TSS_HOBJECT hAuthorizedObject, UINT32 ulPendingFn,
227			TSS_HPOLICY hPolicy, TSS_HPOLICY hUsagePolicy,
228			TSS_HPOLICY hMigPolicy, BYTE sharedSecret[20],
229			TPM_AUTH *auth, BYTE *hashDigest,
230			TCPA_NONCE *nonceEvenOSAP)
231{
232	TSS_RESULT result;
233	UINT32 keyMode, usageMode, migMode = 0;
234
235	if ((result = obj_policy_get_mode(hPolicy, &keyMode)))
236		return result;
237
238	if ((result = obj_policy_get_mode(hUsagePolicy, &usageMode)))
239		return result;
240
241	if (hMigPolicy) {
242		if ((result = obj_policy_get_mode(hMigPolicy, &migMode)))
243			return result;
244	}
245
246	/* ---  If any of them is a callback */
247	if (keyMode == TSS_SECRET_MODE_CALLBACK ||
248	    usageMode == TSS_SECRET_MODE_CALLBACK ||
249	    (hMigPolicy && migMode == TSS_SECRET_MODE_CALLBACK)) {
250		/* ---  And they're not all callback */
251		if (keyMode != TSS_SECRET_MODE_CALLBACK ||
252		    usageMode != TSS_SECRET_MODE_CALLBACK ||
253		    (hMigPolicy && migMode != TSS_SECRET_MODE_CALLBACK))
254			return TSPERR(TSS_E_BAD_PARAMETER);
255	}
256
257	if (keyMode == TSS_SECRET_MODE_CALLBACK) {
258		if ((result = obj_policy_do_hmac(hPolicy, hAuthorizedObject,
259						 TRUE, ulPendingFn,
260						 auth->fContinueAuthSession,
261						 20,
262						 auth->NonceEven.nonce,
263						 NULL,
264						 nonceEvenOSAP->nonce,
265						 auth->NonceOdd.nonce, 20,
266						 hashDigest,
267						 (BYTE *)&auth->HMAC)))
268			return result;
269	} else {
270		HMAC_Auth(sharedSecret, hashDigest, auth);
271	}
272
273	if ((result = obj_policy_dec_counter(hPolicy)))
274		return result;
275
276	if ((result = obj_policy_dec_counter(hUsagePolicy)))
277		return result;
278
279	if (hMigPolicy) {
280		if ((result = obj_policy_dec_counter(hMigPolicy)))
281			return result;
282	}
283
284	return TSS_SUCCESS;
285}
286
287TSS_RESULT
288secret_ValidateAuth_OSAP(TSS_HOBJECT hAuthorizedObject, UINT32 ulPendingFn,
289			 TSS_HPOLICY hPolicy, TSS_HPOLICY hUsagePolicy,
290			 TSS_HPOLICY hMigPolicy, BYTE sharedSecret[20],
291			 TPM_AUTH *auth, BYTE *hashDigest,
292			 TCPA_NONCE *nonceEvenOSAP)
293{
294	TSS_RESULT result;
295	UINT32 keyMode, usageMode, migMode = 0;
296
297	if ((result = obj_policy_get_mode(hPolicy, &keyMode)))
298		return result;
299
300	if ((result = obj_policy_get_mode(hUsagePolicy, &usageMode)))
301		return result;
302
303	if (hMigPolicy) {
304		if ((result = obj_policy_get_mode(hMigPolicy, &migMode)))
305			return result;
306	}
307
308	/* ---  If any of them is a callback */
309	if (keyMode == TSS_SECRET_MODE_CALLBACK ||
310	    usageMode == TSS_SECRET_MODE_CALLBACK ||
311	    (hMigPolicy && migMode == TSS_SECRET_MODE_CALLBACK)) {
312		/* ---  And they're not all callback */
313		if (keyMode != TSS_SECRET_MODE_CALLBACK ||
314		    usageMode != TSS_SECRET_MODE_CALLBACK ||
315		    (hMigPolicy && migMode != TSS_SECRET_MODE_CALLBACK))
316			return TSPERR(TSS_E_BAD_PARAMETER);
317	}
318
319	if (keyMode != TSS_SECRET_MODE_CALLBACK) {
320		if (validateReturnAuth(sharedSecret, hashDigest, auth))
321			return TSPERR(TSS_E_TSP_AUTHFAIL);
322	} else {
323		if ((result = obj_policy_do_hmac(hPolicy, hAuthorizedObject,
324						 FALSE, ulPendingFn,
325						 auth->fContinueAuthSession,
326						 20,
327						 auth->NonceEven.nonce,
328						 NULL,
329						 nonceEvenOSAP->nonce,
330						 auth->NonceOdd.nonce, 20,
331						 hashDigest,
332						 (BYTE *)&auth->HMAC)))
333			return result;
334	}
335
336	return TSS_SUCCESS;
337}
338#endif
339TSS_RESULT
340Init_AuthNonce(TSS_HCONTEXT tspContext, TSS_BOOL cas, TPM_AUTH * auth)
341{
342	TSS_RESULT result;
343
344	auth->fContinueAuthSession = cas;
345	if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
346				       (BYTE **)auth->NonceOdd.nonce))) {
347		LogError("Failed creating random nonce");
348		return TSPERR(TSS_E_INTERNAL_ERROR);
349	}
350
351	return TSS_SUCCESS;
352}
353
354TSS_BOOL
355validateReturnAuth(BYTE *secret, BYTE *hash, TPM_AUTH *auth)
356{
357	BYTE digest[20];
358	/* auth is expected to have both nonces and the digest from the TPM */
359	memcpy(digest, &auth->HMAC, 20);
360	HMAC_Auth(secret, hash, auth);
361
362	return ((TSS_BOOL) (memcmp(digest, &auth->HMAC, 20) != 0));
363}
364
365void
366HMAC_Auth(BYTE * secret, BYTE * Digest, TPM_AUTH * auth)
367{
368	UINT64 offset;
369	BYTE Blob[61];
370
371	offset = 0;
372	Trspi_LoadBlob(&offset, 20, Blob, Digest);
373	Trspi_LoadBlob(&offset, 20, Blob, auth->NonceEven.nonce);
374	Trspi_LoadBlob(&offset, 20, Blob, auth->NonceOdd.nonce);
375	Blob[offset++] = auth->fContinueAuthSession;
376
377	Trspi_HMAC(TSS_HASH_SHA1, 20, secret, offset, Blob, (BYTE *)&auth->HMAC);
378}
379
380TSS_RESULT
381OSAP_Calc(TSS_HCONTEXT tspContext, UINT16 EntityType, UINT32 EntityValue,
382	  BYTE * authSecret, BYTE * usageSecret, BYTE * migSecret,
383	  TCPA_ENCAUTH * encAuthUsage, TCPA_ENCAUTH * encAuthMig,
384	  BYTE * sharedSecret, TPM_AUTH * auth)
385{
386	TSS_RESULT rc;
387	TCPA_NONCE nonceEvenOSAP;
388	UINT64 offset;
389	BYTE hmacBlob[0x200];
390	BYTE hashBlob[0x200];
391	BYTE xorUsageAuth[20];
392	BYTE xorMigAuth[20];
393	UINT32 i;
394
395	if ((rc = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
396				   (BYTE **)auth->NonceOdd.nonce))) {
397		LogError("Failed creating random nonce");
398		return TSPERR(TSS_E_INTERNAL_ERROR);
399	}
400	auth->fContinueAuthSession = 0x00;
401
402	if ((rc = TCS_API(tspContext)->OSAP(tspContext, EntityType, EntityValue, &auth->NonceOdd,
403					    &auth->AuthHandle, &auth->NonceEven, &nonceEvenOSAP))) {
404		if (rc == TCPA_E_RESOURCES) {
405			int retry = 0;
406			do {
407				/* POSIX sleep time, { secs, nanosecs } */
408				struct timespec t = { 0, AUTH_RETRY_NANOSECS };
409
410				nanosleep(&t, NULL);
411
412				rc = TCS_API(tspContext)->OSAP(tspContext, EntityType, EntityValue,
413							       &auth->NonceOdd, &auth->AuthHandle,
414							       &auth->NonceEven, &nonceEvenOSAP);
415			} while (rc == TCPA_E_RESOURCES && ++retry < AUTH_RETRY_COUNT);
416		}
417
418		if (rc)
419			return rc;
420	}
421
422	offset = 0;
423	Trspi_LoadBlob(&offset, 20, hmacBlob, nonceEvenOSAP.nonce);
424	Trspi_LoadBlob(&offset, 20, hmacBlob, auth->NonceOdd.nonce);
425
426	Trspi_HMAC(TSS_HASH_SHA1, 20, authSecret, offset, hmacBlob, sharedSecret);
427
428	offset = 0;
429	Trspi_LoadBlob(&offset, 20, hashBlob, sharedSecret);
430	Trspi_LoadBlob(&offset, 20, hashBlob, auth->NonceEven.nonce);
431
432	if ((rc = Trspi_Hash(TSS_HASH_SHA1, offset, hashBlob, xorUsageAuth)))
433		return rc;
434
435	offset = 0;
436	Trspi_LoadBlob(&offset, 20, hashBlob, sharedSecret);
437	Trspi_LoadBlob(&offset, 20, hashBlob, auth->NonceOdd.nonce);
438	if ((rc = Trspi_Hash(TSS_HASH_SHA1, offset, hashBlob, xorMigAuth)))
439		return rc;
440
441	for (i = 0; i < sizeof(TCPA_ENCAUTH); i++)
442		encAuthUsage->authdata[i] = usageSecret[i] ^ xorUsageAuth[i];
443	for (i = 0; i < sizeof(TCPA_ENCAUTH); i++)
444		encAuthMig->authdata[i] = migSecret[i] ^ xorMigAuth[i];
445
446	return TSS_SUCCESS;
447}
448
449TSS_RESULT
450obj_policy_validate_auth_oiap(TSS_HPOLICY hPolicy, TCPA_DIGEST *hashDigest, TPM_AUTH *auth)
451{
452	TSS_RESULT result = TSS_SUCCESS;
453	struct tsp_object *obj;
454	struct tr_policy_obj *policy;
455	BYTE wellKnown[TCPA_SHA1_160_HASH_LEN] = TSS_WELL_KNOWN_SECRET;
456
457	if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
458		return TSPERR(TSS_E_INVALID_HANDLE);
459
460	policy = (struct tr_policy_obj *)obj->data;
461
462	switch (policy->SecretMode) {
463		case TSS_SECRET_MODE_CALLBACK:
464			result = policy->Tspicb_CallbackHMACAuth(
465					policy->hmacAppData,
466					hPolicy,
467					0,
468					auth->fContinueAuthSession,
469					FALSE,
470					20,
471					auth->NonceEven.nonce,
472					auth->NonceOdd.nonce,
473					NULL, NULL, 20,
474					hashDigest->digest,
475					(BYTE *)&auth->HMAC);
476			break;
477		case TSS_SECRET_MODE_SHA1:
478		case TSS_SECRET_MODE_PLAIN:
479		case TSS_SECRET_MODE_POPUP:
480			if (validateReturnAuth(policy->Secret, hashDigest->digest, auth))
481				result = TSPERR(TSS_E_TSP_AUTHFAIL);
482			break;
483		case TSS_SECRET_MODE_NONE:
484			if (validateReturnAuth(wellKnown, hashDigest->digest, auth))
485				result = TSPERR(TSS_E_TSP_AUTHFAIL);
486			break;
487		default:
488			result = TSPERR(TSS_E_POLICY_NO_SECRET);
489			break;
490	}
491
492	obj_list_put(&policy_list);
493
494	return result;
495}
496
497#if 0
498TSS_RESULT
499authsess_oiap_get(TSS_HOBJECT obj, TPM_COMMAND_CODE ord, TPM_DIGEST *digest, TPM_AUTH *auth)
500{
501	TSS_RESULT result = TSS_SUCCESS;
502	TSS_BOOL bExpired;
503	UINT32 mode;
504	TPM_SECRET secret;
505	TSS_HCONTEXT tspContext;
506	TSS_RESULT (*OIAP)(TSS_HCONTEXT, TCS_AUTHHANDLE *, TPM_NONCE *); // XXX hack
507	TSS_RESULT (*TerminateHandle)(TSS_HCONTEXT, TCS_HANDLE); // XXX hack
508
509
510	if (obj_is_tpm(obj))
511		result = obj_tpm_get_tsp_context(obj, hContext);
512	else if (obj_is_rsakey(obj))
513		result = obj_rsakey_get_tsp_context(obj, hContext);
514	else if (obj_is_encdata(obj))
515		result = obj_encdata_get_tsp_context(obj, hContext);
516	else if (obj_is_nvstore(obj))
517		result = obj_nvstore_get_tsp_context(obj, hContext);
518	else
519		result = TSPERR(TSS_E_INVALID_HANDLE);
520
521#if 0
522	/* This validates that the secret can be used */
523	if ((result = obj_policy_has_expired(hPolicy, &bExpired)))
524		return result;
525
526	if (bExpired == TRUE)
527		return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
528
529	if ((result = obj_policy_get_tsp_context(hPolicy, &tspContext)))
530		return result;
531
532	if ((result = obj_policy_get_mode(hPolicy, &mode)))
533		return result;
534#else
535	if ((result = obj_policy_get_authsess_params()))
536		return result;
537#endif
538	if ((result = Init_AuthNonce(tspContext, cas, auth)))
539		return result;
540
541	/* XXX hack for opening a transport session */
542	if (cas) {
543		OIAP = RPC_OIAP;
544		TerminateHandle = RPC_TerminateHandle;
545	} else {
546		OIAP = TCS_API(tspContext)->OIAP;
547		TerminateHandle = TCS_API(tspContext)->TerminateHandle;
548	}
549
550	/* added retry logic */
551	if ((result = OIAP(tspContext, &auth->AuthHandle, &auth->NonceEven))) {
552		if (result == TCPA_E_RESOURCES) {
553			int retry = 0;
554			do {
555				/* POSIX sleep time, { secs, nanosecs } */
556				struct timespec t = { 0, AUTH_RETRY_NANOSECS };
557
558				nanosleep(&t, NULL);
559
560				result = OIAP(tspContext, &auth->AuthHandle, &auth->NonceEven);
561			} while (result == TCPA_E_RESOURCES && ++retry < AUTH_RETRY_COUNT);
562		}
563
564		if (result)
565			return result;
566	}
567
568	switch (mode) {
569		case TSS_SECRET_MODE_CALLBACK:
570			result = obj_policy_do_hmac(hPolicy, hAuthorizedObject,
571						    TRUE, ulPendingFn,
572						    auth->fContinueAuthSession,
573						    20,
574						    auth->NonceEven.nonce,
575						    auth->NonceOdd.nonce,
576						    NULL, NULL, 20,
577						    hashDigest->digest,
578						    (BYTE *)&auth->HMAC);
579			break;
580		case TSS_SECRET_MODE_SHA1:
581		case TSS_SECRET_MODE_PLAIN:
582		case TSS_SECRET_MODE_POPUP:
583			if ((result = obj_policy_get_secret(hPolicy, TR_SECRET_CTX_NOT_NEW,
584							    &secret)))
585				break;
586
587			HMAC_Auth(secret.authdata, hashDigest->digest, auth);
588			break;
589		case TSS_SECRET_MODE_NONE:
590			/* fall through */
591		default:
592			result = TSPERR(TSS_E_POLICY_NO_SECRET);
593			break;
594	}
595
596	if (result) {
597		TerminateHandle(tspContext, auth->AuthHandle);
598		return result;
599	}
600
601	return obj_policy_dec_counter(hPolicy);
602}
603
604TSS_RESULT
605authsess_oiap_put(TPM_AUTH *auth)
606{
607}
608#endif
609
610#ifdef TSS_BUILD_DELEGATION
611TSS_RESULT
612authsess_do_dsap(struct authsess *sess)
613{
614	TSS_RESULT result;
615
616	if ((result = TCS_API(sess->tspContext)->DSAP(sess->tspContext, sess->entity_type,
617						      sess->obj_parent, &sess->nonceOddxSAP,
618						      sess->entityValueSize, sess->entityValue,
619						      &sess->pAuth->AuthHandle,
620						      &sess->pAuth->NonceEven,
621						      &sess->nonceEvenxSAP))) {
622		if (result == TCPA_E_RESOURCES) {
623			int retry = 0;
624			do {
625				/* POSIX sleep time, { secs, nanosecs } */
626				struct timespec t = { 0, AUTH_RETRY_NANOSECS };
627
628				nanosleep(&t, NULL);
629
630				result = TCS_API(sess->tspContext)->DSAP(sess->tspContext,
631									 sess->entity_type,
632									 sess->obj_parent,
633									 &sess->nonceOddxSAP,
634									 sess->entityValueSize,
635									 sess->entityValue,
636									 &sess->pAuth->AuthHandle,
637									 &sess->pAuth->NonceEven,
638									 &sess->nonceEvenxSAP);
639			} while (result == TCPA_E_RESOURCES && ++retry < AUTH_RETRY_COUNT);
640		}
641	}
642
643	return result;
644}
645#endif
646
647TSS_RESULT
648authsess_do_osap(struct authsess *sess)
649{
650	TSS_RESULT result;
651
652	if ((result = TCS_API(sess->tspContext)->OSAP(sess->tspContext, sess->entity_type,
653						      sess->obj_parent, &sess->nonceOddxSAP,
654						      &sess->pAuth->AuthHandle,
655						      &sess->pAuth->NonceEven,
656						      &sess->nonceEvenxSAP))) {
657		if (result == TCPA_E_RESOURCES) {
658			int retry = 0;
659			do {
660				/* POSIX sleep time, { secs, nanosecs } */
661				struct timespec t = { 0, AUTH_RETRY_NANOSECS };
662
663				nanosleep(&t, NULL);
664
665				result = TCS_API(sess->tspContext)->OSAP(sess->tspContext,
666									 sess->entity_type,
667									 sess->obj_parent,
668									 &sess->nonceOddxSAP,
669									 &sess->pAuth->AuthHandle,
670									 &sess->pAuth->NonceEven,
671									 &sess->nonceEvenxSAP);
672			} while (result == TCPA_E_RESOURCES && ++retry < AUTH_RETRY_COUNT);
673		}
674	}
675
676	return result;
677}
678
679TSS_RESULT
680authsess_callback_xor(PVOID lpAppData,
681		      TSS_HOBJECT hOSAPObject,
682		      TSS_HOBJECT hObject,
683		      TSS_FLAG PurposeSecret,
684		      UINT32 ulSizeNonces,
685		      BYTE *rgbNonceEven,
686		      BYTE *rgbNonceOdd,
687		      BYTE *rgbNonceEvenOSAP,
688		      BYTE *rgbNonceOddOSAP,
689		      UINT32 ulSizeEncAuth,
690		      BYTE *rgbEncAuthUsage,
691		      BYTE *rgbEncAuthMigration)
692{
693	TSS_RESULT result;
694	BYTE xorUseAuth[sizeof(TPM_DIGEST)];
695	BYTE xorMigAuth[sizeof(TPM_DIGEST)];
696	Trspi_HashCtx hashCtx;
697	UINT32 i;
698	struct authsess *sess = (struct authsess *)lpAppData;
699
700	/* sess->sharedSecret was calculated in authsess_xsap_init */
701
702	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
703	result |= Trspi_Hash_SECRET(&hashCtx, sess->sharedSecret.digest);
704	result |= Trspi_Hash_NONCE(&hashCtx, rgbNonceEven);
705	if ((result |= Trspi_HashFinal(&hashCtx, xorUseAuth)))
706		return result;
707
708	for (i = 0; i < ulSizeEncAuth; i++)
709		rgbEncAuthUsage[i] ^= xorUseAuth[i];
710
711	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
712	result |= Trspi_Hash_SECRET(&hashCtx, sess->sharedSecret.digest);
713	result |= Trspi_Hash_NONCE(&hashCtx, rgbNonceOdd);
714	if ((result |= Trspi_HashFinal(&hashCtx, xorMigAuth)))
715		return result;
716
717	for (i = 0; i < ulSizeEncAuth; i++)
718		rgbEncAuthMigration[i] ^= xorMigAuth[i];
719
720	return TSS_SUCCESS;
721}
722
723TSS_RESULT
724authsess_callback_hmac(PVOID lpAppData,
725		       TSS_HOBJECT hAuthorizedObject,
726		       TSS_BOOL ReturnOrVerify,
727		       UINT32 ulPendingFunction,
728		       TSS_BOOL ContinueUse,
729		       UINT32 ulSizeNonces,
730		       BYTE *rgbNonceEven,
731		       BYTE *rgbNonceOdd,
732		       BYTE *rgbNonceEvenOSAP,
733		       BYTE *rgbNonceOddOSAP,
734		       UINT32 ulSizeDigestHmac,
735		       BYTE *rgbParamDigest,
736		       BYTE *rgbHmacData)
737{
738	struct authsess *sess = (struct authsess *)lpAppData;
739	TSS_RESULT result = TSS_SUCCESS;
740	UINT64 offset;
741	BYTE Blob[61];
742
743	offset = 0;
744	Trspi_LoadBlob(&offset, ulSizeDigestHmac, Blob, rgbParamDigest);
745	Trspi_LoadBlob(&offset, ulSizeNonces, Blob, rgbNonceEven);
746	Trspi_LoadBlob(&offset, ulSizeNonces, Blob, rgbNonceOdd);
747	Blob[offset++] = ContinueUse;
748
749	if (ReturnOrVerify) {
750		Trspi_HMAC(TSS_HASH_SHA1, ulSizeDigestHmac, sess->sharedSecret.digest, offset, Blob,
751			   rgbHmacData);
752	} else {
753		TPM_HMAC hmacVerify;
754
755		Trspi_HMAC(TSS_HASH_SHA1, ulSizeDigestHmac, sess->sharedSecret.digest, offset, Blob,
756			   hmacVerify.digest);
757		result = memcmp(rgbHmacData, hmacVerify.digest, ulSizeDigestHmac);
758		if (result)
759			result = TPM_E_AUTHFAIL;
760	}
761
762	return result;
763}
764
765/* Create an OSAP session. @requirements is used in different ways depending on the command to
766 * indicate whether we should require a policy or auth value */
767TSS_RESULT
768authsess_xsap_init(TSS_HCONTEXT     tspContext,
769		   TSS_HOBJECT	    obj_parent,
770		   TSS_HOBJECT      obj_child,
771		   TSS_BOOL	    requirements,
772		   TPM_COMMAND_CODE command,
773		   TPM_ENTITY_TYPE  entity_type,
774		   struct authsess  **xsess)
775{
776	TSS_RESULT result;
777	TSS_BOOL authdatausage = FALSE, req_auth = TRUE, get_child_auth = TRUE, secret_set = FALSE;
778	BYTE hmacBlob[2 * sizeof(TPM_DIGEST)];
779	UINT64 offset;
780	TSS_BOOL new_secret = TR_SECRET_CTX_NOT_NEW;
781	struct authsess *sess;
782
783	if ((sess = calloc(1, sizeof(struct authsess))) == NULL) {
784		LogError("malloc of %zd bytes failed", sizeof(struct authsess));
785		return TSPERR(TSS_E_OUTOFMEMORY);
786	}
787
788	switch (command) {
789	/* Parent is Key for the cases below */
790	case TPM_ORD_Delegate_CreateKeyDelegation:
791	case TPM_ORD_CreateWrapKey:
792	case TPM_ORD_CMK_CreateKey:
793	case TPM_ORD_Seal:
794	case TPM_ORD_Sealx:
795	case TPM_ORD_Unseal:
796	case TPM_ORD_ChangeAuth:
797		if ((result = obj_rsakey_get_policy(obj_parent, TSS_POLICY_USAGE,
798						    &sess->hUsageParent, NULL)))
799			goto error;
800		break;
801	/* Parent is TPM for the cases below */
802	case TPM_ORD_Delegate_CreateOwnerDelegation:
803		req_auth = FALSE;
804		/* fall through */
805	case TPM_ORD_MakeIdentity:
806	case TPM_ORD_NV_DefineSpace:
807		if ((result = obj_tpm_get_policy(obj_parent, TSS_POLICY_USAGE,
808						 &sess->hUsageParent)))
809			goto error;
810		break;
811	case TPM_ORD_ChangeAuthOwner:
812		/* Special case, ChangeAuthOwner is used to change Owner and SRK auth */
813		if (obj_is_rsakey(obj_parent)) {
814			if ((result = obj_rsakey_get_policy(obj_parent, TSS_POLICY_USAGE,
815							    &sess->hUsageParent, NULL)))
816				goto error;
817		} else {
818			if ((result = obj_tpm_get_policy(obj_parent, TSS_POLICY_USAGE,
819							 &sess->hUsageParent)))
820				goto error;
821		}
822		break;
823	default:
824		result = TSPERR(TSS_E_INTERNAL_ERROR);
825		goto error;
826	}
827
828	if (requirements && !sess->hUsageParent) {
829		result = TSPERR(TSS_E_TSP_AUTHREQUIRED);
830		goto error;
831	}
832
833	if (sess->hUsageParent) {
834		/* These are trousers callback functions which will be used to process the auth
835		 * session. If the policy type is callback for hUsageParent, they will be
836		 * overwritten by the application defined callback functions in the policy */
837		sess->cb_xor.callback = authsess_callback_xor;
838		sess->cb_xor.appData = (PVOID)sess;
839		sess->cb_hmac.callback = authsess_callback_hmac;
840		sess->cb_hmac.appData = (PVOID)sess;
841
842		/* XXX the parent object doesn't always hold the callbacks */
843		if ((result = obj_policy_get_xsap_params(sess->hUsageParent, command,
844							 &sess->entity_type, &sess->entityValueSize,
845							 &sess->entityValue,
846							 sess->parentSecret.authdata, &sess->cb_xor,
847							 &sess->cb_hmac, NULL, &sess->parentMode,
848							 new_secret)))
849			goto error;
850	} else
851		sess->parentMode = TSS_SECRET_MODE_NONE;
852
853	switch (command) {
854	/* Child is a Key object */
855	case TPM_ORD_CreateWrapKey:
856	case TPM_ORD_CMK_CreateKey:
857		if ((result = obj_rsakey_get_policies(obj_child, &sess->hUsageChild,
858						      &sess->hMigChild, &authdatausage)))
859			goto error;
860
861		if (authdatausage && !sess->hUsageChild) {
862			result = TSPERR(TSS_E_TSP_AUTHREQUIRED);
863			goto error;
864		}
865
866		if (obj_rsakey_is_migratable(obj_child)) {
867			if (!sess->hMigChild) {
868				result = TSPERR(TSS_E_KEY_NO_MIGRATION_POLICY);
869				goto error;
870			}
871
872			if ((result = obj_policy_get_xsap_params(sess->hMigChild, 0, NULL, NULL,
873								 NULL, sess->encAuthMig.authdata,
874								 NULL, NULL, NULL, &sess->mMode,
875								 new_secret)))
876				goto error;
877		}
878
879		if ((result = obj_rsakey_get_tcs_handle(obj_parent, &sess->obj_parent)))
880			goto error;
881		break;
882	/* Child is an Encdata object */
883	case TPM_ORD_Unseal:
884#ifdef TSS_BUILD_SEALX
885	case TPM_ORD_Sealx:
886		/* These may be overwritten down below, when obj_policy_get_xsap_params is called
887		 * on the child usage policy */
888		sess->cb_sealx.callback = sealx_mask_cb;
889		sess->cb_sealx.appData = (PVOID)sess;
890		/* fall through */
891#endif
892	case TPM_ORD_Seal:
893		if ((result = obj_encdata_get_policy(obj_child, TSS_POLICY_USAGE,
894						     &sess->hUsageChild)))
895			goto error;
896
897		if ((result = obj_rsakey_get_tcs_handle(obj_parent, &sess->obj_parent)))
898			goto error;
899		break;
900#ifdef TSS_BUILD_NV
901	/* Child is an NV object */
902	case TPM_ORD_NV_DefineSpace:
903		/* The requirements variable tells us whether nv object auth is required */
904		req_auth = requirements;
905
906		if (req_auth) {
907			if (sess->parentMode == TSS_SECRET_MODE_NONE) {
908				result = TSPERR(TSS_E_TSP_AUTHREQUIRED);
909				goto error;
910			}
911
912			if ((result = obj_nvstore_get_policy(obj_child, TSS_POLICY_USAGE,
913							     &sess->hUsageChild)))
914				goto error;
915
916			/* According to the spec, we must fall back on the TSP context's policy for
917			 * auth if none is set in the NV object */
918			if (!sess->hUsageChild) {
919				if ((result = obj_context_get_policy(tspContext, TSS_POLICY_USAGE,
920								     &sess->hUsageChild)))
921					goto error;
922			}
923
924			if ((result = obj_policy_is_secret_set(sess->hUsageChild, &secret_set)))
925				goto error;
926
927			if (!secret_set) {
928				result = TSPERR(TSS_E_TSP_AUTHREQUIRED);
929				goto error;
930			}
931		} else {
932			/* In this case, the TPM is owned, but we're creating a no-auth NV area */
933			get_child_auth = FALSE;
934		}
935
936		break;
937#endif
938	/* Child is a Key object */
939	case TPM_ORD_MakeIdentity:
940		if ((result = obj_rsakey_get_policy(obj_child, TSS_POLICY_USAGE,
941						    &sess->hUsageChild, NULL)))
942			goto error;
943		break;
944	/* Child is a Policy object */
945	case TPM_ORD_Delegate_CreateKeyDelegation:
946	case TPM_ORD_ChangeAuth:
947		if ((result = obj_rsakey_get_tcs_handle(obj_parent, &sess->obj_parent)))
948			goto error;
949		/* fall through */
950	case TPM_ORD_Delegate_CreateOwnerDelegation:
951	case TPM_ORD_ChangeAuthOwner:
952		sess->hUsageChild = obj_child;
953		new_secret = TR_SECRET_CTX_NEW;
954		break;
955	default:
956		result = TSPERR(TSS_E_INTERNAL_ERROR);
957		goto error;
958	}
959
960	/* If req_auth is FALSE here, we don't actually need to set up an auth session, so returning
961	 * is OK.  At this point, authsess->pAuth is NULL, so the TCS API will not get any
962	 * authdata. */
963	if (req_auth == FALSE && sess->parentMode == TSS_SECRET_MODE_NONE)
964		goto done;
965
966	if (get_child_auth) {
967		if ((result = obj_policy_get_xsap_params(sess->hUsageChild, 0, 0, NULL, NULL,
968							 sess->encAuthUse.authdata, NULL, NULL,
969							 &sess->cb_sealx, &sess->uMode,
970							 new_secret)))
971			goto error;
972	}
973
974	if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
975				       (BYTE **)sess->nonceOddxSAP.nonce)))
976		goto error;
977
978	sess->obj_child = obj_child;
979	sess->tspContext = tspContext;
980	sess->pAuth = &sess->auth;
981	sess->command = command;
982
983#ifdef TSS_BUILD_DELEGATION
984	/* if entityValue is set, we have a custom entity, i.e. delegation blob or row */
985	if (sess->entityValue) {
986		/* DSAP's entity type was pulled from the policy in the authsess_xsap_init call
987		 * above */
988		if ((result = authsess_do_dsap(sess)))
989			goto error;
990	}
991#endif
992	if (!sess->entityValue) {
993		sess->entity_type = entity_type;
994		if ((result = authsess_do_osap(sess)))
995			goto error;
996	}
997
998	if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
999				       (BYTE **)sess->auth.NonceOdd.nonce)))
1000		goto error;
1001
1002	/* We have both OSAP nonces, so calculate the shared secret if we're responsible for it */
1003	if (sess->parentMode != TSS_SECRET_MODE_CALLBACK) {
1004		offset = 0;
1005		Trspi_LoadBlob(&offset, sizeof(TPM_NONCE), hmacBlob, sess->nonceEvenxSAP.nonce);
1006		Trspi_LoadBlob(&offset, sizeof(TPM_NONCE), hmacBlob, sess->nonceOddxSAP.nonce);
1007
1008		if ((result = Trspi_HMAC(TSS_HASH_SHA1, sizeof(TPM_ENCAUTH),
1009					 sess->parentSecret.authdata, offset, hmacBlob,
1010					 sess->sharedSecret.digest)))
1011			goto error;
1012	}
1013
1014	/* XXX What does a PurposeSecret of TRUE mean here? */
1015	if ((result =
1016	     ((TSS_RESULT (*)(PVOID, TSS_HOBJECT, TSS_HOBJECT, TSS_FLAG,
1017	       UINT32, BYTE *, BYTE *, BYTE *, BYTE *, UINT32, BYTE *,
1018	       BYTE *))sess->cb_xor.callback)(sess->cb_xor.appData, sess->hUsageParent,
1019					      sess->hUsageChild, TRUE, sizeof(TPM_DIGEST),
1020					      sess->auth.NonceEven.nonce, sess->auth.NonceOdd.nonce,
1021					      sess->nonceEvenxSAP.nonce, sess->nonceOddxSAP.nonce,
1022					      sizeof(TPM_ENCAUTH), sess->encAuthUse.authdata,
1023					      sess->encAuthMig.authdata)))
1024		return result;
1025
1026done:
1027	*xsess = sess;
1028
1029	return TSS_SUCCESS;
1030error:
1031	free(sess);
1032	return result;
1033}
1034
1035TSS_RESULT
1036authsess_xsap_hmac(struct authsess *sess, TPM_DIGEST *digest)
1037{
1038	TSS_RESULT result;
1039
1040	/* If no auth session was established using this authsess object, return success */
1041	if (!sess->pAuth)
1042		return TSS_SUCCESS;
1043
1044	/* XXX Placeholder for future continueAuthSession support:
1045	 *      conditionally bump NonceOdd if continueAuthSession == TRUE here
1046	 */
1047
1048	if ((result =
1049	    ((TSS_RESULT (*)(PVOID, TSS_HOBJECT, TSS_BOOL,
1050	      UINT32, TSS_BOOL, UINT32, BYTE *, BYTE *,
1051	      BYTE *, BYTE *, UINT32, BYTE *,
1052	      BYTE *))sess->cb_hmac.callback)(sess->cb_hmac.appData,
1053					      sess->hUsageParent, TRUE, sess->command,
1054					      sess->auth.fContinueAuthSession, sizeof(TPM_NONCE),
1055					      sess->auth.NonceEven.nonce,
1056					      sess->auth.NonceOdd.nonce,
1057					      sess->nonceEvenxSAP.nonce,
1058					      sess->nonceOddxSAP.nonce, sizeof(TPM_DIGEST),
1059					      digest->digest, sess->auth.HMAC.authdata)))
1060		return result;
1061
1062	if (sess->hUsageParent)
1063		obj_policy_dec_counter(sess->hUsageParent);
1064
1065	if (sess->hUsageChild)
1066		obj_policy_dec_counter(sess->hUsageChild);
1067
1068	if (sess->hMigChild)
1069		obj_policy_dec_counter(sess->hMigChild);
1070
1071	return TSS_SUCCESS;
1072}
1073
1074TSS_RESULT
1075authsess_xsap_verify(struct authsess *sess, TPM_DIGEST *digest)
1076{
1077	/* If no auth session was established using this authsess object, return success */
1078	if (!sess->pAuth)
1079		return TSS_SUCCESS;
1080
1081	return ((TSS_RESULT (*)(PVOID, TSS_HOBJECT, TSS_BOOL,
1082		 UINT32, TSS_BOOL, UINT32, BYTE *, BYTE *,
1083		 BYTE *, BYTE *, UINT32, BYTE *,
1084		 BYTE *))sess->cb_hmac.callback)(sess->cb_hmac.appData,
1085						 sess->hUsageParent, FALSE, sess->command,
1086						 sess->auth.fContinueAuthSession, sizeof(TPM_NONCE),
1087						 sess->auth.NonceEven.nonce,
1088						 sess->auth.NonceOdd.nonce,
1089						 sess->nonceEvenxSAP.nonce,
1090						 sess->nonceOddxSAP.nonce, sizeof(TPM_DIGEST),
1091						 digest->digest, sess->auth.HMAC.authdata);
1092}
1093
1094TSS_RESULT
1095__tspi_free_resource(TSS_HCONTEXT tspContext, UINT32 handle, UINT32 resourceType)
1096{
1097	TSS_RESULT result = TSS_SUCCESS;
1098#ifdef TSS_BUILD_TSS12
1099	UINT32 version = 0;
1100
1101	if ((result = obj_context_get_tpm_version(tspContext, &version)))
1102		return result;
1103
1104	if (version == 2) {
1105		return TCS_API(tspContext)->FlushSpecific(tspContext, handle, resourceType);
1106	}
1107#endif
1108
1109	switch (resourceType) {
1110		case TPM_RT_KEY:
1111			result = TCS_API(tspContext)->EvictKey(tspContext, handle);
1112			break;
1113		case TPM_RT_AUTH:
1114			result = TCS_API(tspContext)->TerminateHandle(tspContext, handle);
1115			break;
1116		default:
1117			LogDebugFn("Trying to free TPM 1.2 resource type 0x%x on 1.1 TPM!",
1118				   resourceType);
1119			result = TSPERR(TSS_E_INTERNAL_ERROR);
1120			break;
1121	}
1122
1123	return result;
1124}
1125
1126void
1127authsess_free(struct authsess *xsap)
1128{
1129	if (xsap) {
1130		if (xsap->auth.AuthHandle && xsap->auth.fContinueAuthSession)
1131			(void)__tspi_free_resource(xsap->tspContext, xsap->auth.AuthHandle, TPM_RT_AUTH);
1132
1133		free(xsap->entityValue);
1134		free(xsap);
1135		xsap = NULL;
1136	}
1137}
1138
1139#ifdef TSS_BUILD_TRANSPORT
1140TSS_RESULT
1141Transport_OIAP(TSS_HCONTEXT    tspContext,   /* in */
1142	       TCS_AUTHHANDLE* authHandle,   /* out */
1143	       TPM_NONCE*      nonce0)       /* out */
1144{
1145	TSS_RESULT result;
1146	UINT32 decLen = 0;
1147	BYTE *dec = NULL;
1148	UINT64 offset;
1149	TCS_HANDLE handlesLen = 0;
1150
1151	if ((result = obj_context_transport_init(tspContext)))
1152		return result;
1153
1154	LogDebugFn("Executing in a transport session");
1155
1156	if ((result = obj_context_transport_execute(tspContext, TPM_ORD_OIAP, 0, NULL, NULL,
1157						    &handlesLen, NULL, NULL, NULL, &decLen, &dec)))
1158		return result;
1159
1160	if (decLen != sizeof(TCS_AUTHHANDLE) + sizeof(TPM_NONCE))
1161		return TSPERR(TSS_E_INTERNAL_ERROR);
1162
1163	offset = 0;
1164	Trspi_UnloadBlob_UINT32(&offset, authHandle, dec);
1165	Trspi_UnloadBlob_NONCE(&offset, dec, nonce0);
1166
1167	return result;
1168}
1169
1170TSS_RESULT
1171Transport_OSAP(TSS_HCONTEXT    tspContext,	/* in */
1172	       TPM_ENTITY_TYPE entityType,	/* in */
1173	       UINT32          entityValue,	/* in */
1174	       TPM_NONCE*      nonceOddOSAP,	/* in */
1175	       TCS_AUTHHANDLE* authHandle,	/* out */
1176	       TPM_NONCE*      nonceEven,	/* out */
1177	       TPM_NONCE*      nonceEvenOSAP)	/* out */
1178{
1179	TSS_RESULT result;
1180	UINT32 decLen = 0;
1181	BYTE *dec = NULL;
1182	UINT64 offset;
1183	TCS_HANDLE handlesLen = 0;
1184	BYTE data[sizeof(UINT16) + sizeof(UINT32) + sizeof(TPM_NONCE)];
1185
1186	if ((result = obj_context_transport_init(tspContext)))
1187		return result;
1188
1189	LogDebugFn("Executing in a transport session");
1190
1191	offset = 0;
1192	Trspi_LoadBlob_UINT16(&offset, entityType, data);
1193	Trspi_LoadBlob_UINT32(&offset, entityValue, data);
1194	Trspi_LoadBlob_NONCE(&offset, data, nonceOddOSAP);
1195
1196	if ((result = obj_context_transport_execute(tspContext, TPM_ORD_OSAP, sizeof(data), data,
1197						    NULL, &handlesLen, NULL, NULL, NULL, &decLen,
1198						    &dec)))
1199		return result;
1200
1201	offset = 0;
1202	Trspi_UnloadBlob_UINT32(&offset, authHandle, dec);
1203	Trspi_UnloadBlob_NONCE(&offset, dec, nonceEven);
1204	Trspi_UnloadBlob_NONCE(&offset, dec, nonceEvenOSAP);
1205
1206	return TSS_SUCCESS;
1207}
1208
1209TSS_RESULT
1210Transport_TerminateHandle(TSS_HCONTEXT tspContext, /* in */
1211			  TCS_AUTHHANDLE handle)   /* in */
1212{
1213	TSS_RESULT result;
1214	TCS_HANDLE handlesLen = 0, *handles, *handles_track;
1215
1216	/* Call ExecuteTransport */
1217	handlesLen = 1;
1218	if ((handles = malloc(sizeof(TCS_HANDLE))) == NULL) {
1219		LogError("malloc of %zd bytes failed", sizeof(TCS_HANDLE));
1220		return TSPERR(TSS_E_OUTOFMEMORY);
1221	}
1222
1223	*handles = handle;
1224    handles_track = handles;
1225
1226    // Since the call tree of this function can possibly alloc memory
1227    // (check RPC_ExecuteTransport_TP function), its better to keep track of
1228    // the handle.
1229	result = obj_context_transport_execute(tspContext, TPM_ORD_Terminate_Handle, 0, NULL,
1230					       NULL, &handlesLen, &handles, NULL, NULL, NULL, NULL);
1231
1232	free(handles);
1233    handles = NULL;
1234    free(handles_track);
1235
1236	return result;
1237}
1238#endif
1239