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-2006
8  *
9  */
10 
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <limits.h>
15 
16 #include "trousers/tss.h"
17 #include "trousers_types.h"
18 #include "tcs_tsp.h"
19 #include "tcs_utils.h"
20 #include "tcs_int_literals.h"
21 #include "capabilities.h"
22 #include "tcslog.h"
23 #include "tcsd_wrap.h"
24 #include "tcsd.h"
25 #include "auth_mgr.h"
26 #include "req_mgr.h"
27 
28 
29 MUTEX_DECLARE_EXTERN(tcsp_lock);
30 
31 /* Note: The after taking the auth_mgr_lock in any of the functions below, the
32  * mem_cache_lock cannot be taken without risking a deadlock. So, the auth_mgr
33  * functions must be "self-contained" wrt locking */
34 
35 /* no locking done in init since its called by only a single thread */
36 TSS_RESULT
auth_mgr_init()37 auth_mgr_init()
38 {
39           memset(&auth_mgr, 0, sizeof(struct _auth_mgr));
40 
41           auth_mgr.max_auth_sessions = tpm_metrics.num_auths;
42 
43           auth_mgr.overflow = calloc(TSS_DEFAULT_OVERFLOW_AUTHS, sizeof(COND_VAR *));
44           if (auth_mgr.overflow == NULL) {
45                     LogError("malloc of %zd bytes failed",
46                                (TSS_DEFAULT_OVERFLOW_AUTHS * sizeof(COND_VAR *)));
47                     return TCSERR(TSS_E_OUTOFMEMORY);
48           }
49           auth_mgr.overflow_size = TSS_DEFAULT_OVERFLOW_AUTHS;
50 
51           auth_mgr.auth_mapper = calloc(TSS_DEFAULT_AUTH_TABLE_SIZE, sizeof(struct auth_map));
52           if (auth_mgr.auth_mapper == NULL) {
53                     LogError("malloc of %zd bytes failed",
54                                (TSS_DEFAULT_AUTH_TABLE_SIZE * sizeof(struct auth_map)));
55                     return TCSERR(TSS_E_OUTOFMEMORY);
56           }
57           auth_mgr.auth_mapper_size = TSS_DEFAULT_AUTH_TABLE_SIZE;
58 
59           return TSS_SUCCESS;
60 }
61 
62 TSS_RESULT
auth_mgr_final()63 auth_mgr_final()
64 {
65           UINT32 i;
66 
67           /* wake up any sleeping threads, so they can be joined */
68           for (i = 0; i < auth_mgr.overflow_size; i++) {
69                     if (auth_mgr.overflow[i] != NULL)
70                               COND_SIGNAL(auth_mgr.overflow[i]);
71           }
72 
73           free(auth_mgr.overflow);
74           free(auth_mgr.auth_mapper);
75 
76           return TSS_SUCCESS;
77 }
78 
79 TSS_RESULT
auth_mgr_save_ctx(TCS_CONTEXT_HANDLE hContext)80 auth_mgr_save_ctx(TCS_CONTEXT_HANDLE hContext)
81 {
82        TSS_RESULT result = TSS_SUCCESS;
83           UINT32 i;
84 
85           for (i = 0; i < auth_mgr.auth_mapper_size; i++) {
86                     if (auth_mgr.auth_mapper[i].full == TRUE &&
87                         auth_mgr.auth_mapper[i].swap == NULL &&
88                         auth_mgr.auth_mapper[i].tcs_ctx != hContext) {
89                               LogDebug("Calling TPM_SaveAuthContext for TCS CTX %x. Swapping out: TCS %x "
90                                          "TPM %x", hContext, auth_mgr.auth_mapper[i].tcs_ctx,
91                                          auth_mgr.auth_mapper[i].tpm_handle);
92 
93                               if ((result = TPM_SaveAuthContext(auth_mgr.auth_mapper[i].tpm_handle,
94                                                                         &auth_mgr.auth_mapper[i].swap_size,
95                                                                         &auth_mgr.auth_mapper[i].swap))) {
96                                         LogDebug("TPM_SaveAuthContext failed: 0x%x", result);
97                                         return result;
98                               }
99                        break;
100                     }
101           }
102 
103        return result;
104 }
105 
106 /* if there's a TCS context waiting to get auth, wake it up or swap it in */
107 void
auth_mgr_swap_in()108 auth_mgr_swap_in()
109 {
110           if (auth_mgr.overflow[auth_mgr.of_tail] != NULL) {
111                     LogDebug("waking up thread %lddd, auth slot has opened", THREAD_ID);
112                     /* wake up the next sleeping thread in order and increment tail */
113                     COND_SIGNAL(auth_mgr.overflow[auth_mgr.of_tail]);
114                     auth_mgr.overflow[auth_mgr.of_tail] = NULL;
115                     auth_mgr.of_tail = (auth_mgr.of_tail + 1) % auth_mgr.overflow_size;
116           } else {
117                     /* else nobody needs to be swapped in, so continue */
118                     LogDebug("no threads need to be signaled.");
119           }
120 }
121 
122 /* we need to swap out an auth context or add a waiting context to the overflow queue */
123 TSS_RESULT
auth_mgr_swap_out(TCS_CONTEXT_HANDLE hContext)124 auth_mgr_swap_out(TCS_CONTEXT_HANDLE hContext)
125 {
126           COND_VAR *cond;
127 
128           /* If the TPM can do swapping and it succeeds, return, else cond wait below */
129           if (tpm_metrics.authctx_swap && !auth_mgr_save_ctx(hContext))
130                     return TSS_SUCCESS;
131 
132           if ((cond = ctx_get_cond_var(hContext)) == NULL) {
133                     LogError("Auth swap variable not found for TCS context 0x%x", hContext);
134                     return TCSERR(TSS_E_INTERNAL_ERROR);
135           }
136 
137           /* Test whether we are the last awake thread.  If we are, we can't go to sleep
138            * since then there'd be no worker thread to wake the others up. This situation
139            * can arise when we're on a busy system who's TPM doesn't support auth ctx
140            * swapping.
141            */
142           if (auth_mgr.sleeping_threads == (tcsd_options.num_threads - 1)) {
143                     LogError("auth mgr failing: too many threads already waiting");
144                     LogTPMERR(TCPA_E_RESOURCES, __FILE__, __LINE__);
145                     return TCPA_E_RESOURCES;
146           }
147 
148           if (auth_mgr.overflow[auth_mgr.of_head] == NULL) {
149                     auth_mgr.overflow[auth_mgr.of_head] = cond;
150                     auth_mgr.of_head = (auth_mgr.of_head + 1) % auth_mgr.overflow_size;
151                     /* go to sleep */
152                     LogDebug("thread %lddd going to sleep until auth slot opens", THREAD_ID);
153                     auth_mgr.sleeping_threads++;
154                     COND_WAIT(cond, &tcsp_lock);
155                     auth_mgr.sleeping_threads--;
156           } else if (auth_mgr.overflow_size + TSS_DEFAULT_OVERFLOW_AUTHS < UINT_MAX) {
157                     COND_VAR **tmp = auth_mgr.overflow;
158 
159                     LogDebugFn("Table of sleeping threads is full (%hu), growing to %hu entries",
160                                  auth_mgr.sleeping_threads,
161                                  auth_mgr.overflow_size + TSS_DEFAULT_OVERFLOW_AUTHS);
162 
163                     auth_mgr.overflow = calloc(auth_mgr.overflow_size + TSS_DEFAULT_OVERFLOW_AUTHS,
164                                                      sizeof(COND_VAR *));
165                     if (auth_mgr.overflow == NULL) {
166                               LogDebugFn("malloc of %zd bytes failed",
167                                            (auth_mgr.overflow_size + TSS_DEFAULT_OVERFLOW_AUTHS) *
168                                            sizeof(COND_VAR *));
169                               auth_mgr.overflow = tmp;
170                               return TCSERR(TSS_E_OUTOFMEMORY);
171                     }
172                     auth_mgr.overflow_size += TSS_DEFAULT_OVERFLOW_AUTHS;
173 
174                     LogDebugFn("Success.");
175                     memcpy(auth_mgr.overflow, tmp, auth_mgr.sleeping_threads * sizeof(COND_VAR *));
176                     free(tmp);
177 
178                     /* XXX This could temporarily wake threads up out of order */
179                     auth_mgr.of_head = auth_mgr.sleeping_threads;
180                     auth_mgr.of_tail = 0;
181                     auth_mgr.overflow[auth_mgr.of_head] = cond;
182                     auth_mgr.of_head = (auth_mgr.of_head + 1) % auth_mgr.overflow_size;
183                     LogDebug("thread %lddd going to sleep until auth slot opens", THREAD_ID);
184                     auth_mgr.sleeping_threads++;
185                     COND_WAIT(cond, &tcsp_lock);
186                     auth_mgr.sleeping_threads--;
187           } else {
188                     LogError("Auth table overflow is full (%u entries), some will fail.",
189                                auth_mgr.overflow_size);
190                     return TCSERR(TSS_E_INTERNAL_ERROR);
191           }
192 
193           return TSS_SUCCESS;
194 }
195 
196 /* close all auth contexts associated with this TCS_CONTEXT_HANDLE */
197 TSS_RESULT
auth_mgr_close_context(TCS_CONTEXT_HANDLE tcs_handle)198 auth_mgr_close_context(TCS_CONTEXT_HANDLE tcs_handle)
199 {
200           UINT32 i;
201           TSS_RESULT result;
202 
203           for (i = 0; i < auth_mgr.auth_mapper_size; i++) {
204                     if (auth_mgr.auth_mapper[i].full == TRUE &&
205                         auth_mgr.auth_mapper[i].tcs_ctx == tcs_handle) {
206                               if (auth_mgr.auth_mapper[i].swap) {
207                                         /* This context is swapped out of the TPM, so we can just free the
208                                          * blob */
209                                         free(auth_mgr.auth_mapper[i].swap);
210                                         auth_mgr.auth_mapper[i].swap = NULL;
211                                         auth_mgr.auth_mapper[i].swap_size = 0;
212                               } else {
213                                         result = TCSP_FlushSpecific_Common(auth_mgr.auth_mapper[i].tpm_handle,
214                                                                                    TPM_RT_AUTH);
215 
216                                         /* Ok, probably dealing with a 1.1 TPM */
217                                         if (result == TPM_E_BAD_ORDINAL)
218                                        result = internal_TerminateHandle(
219                                            auth_mgr.auth_mapper[i].tpm_handle);
220 
221                                         if (result == TCPA_E_INVALID_AUTHHANDLE) {
222                                                   LogDebug("Tried to close an invalid auth handle: %x",
223                                                              auth_mgr.auth_mapper[i].tpm_handle);
224                                         } else if (result != TCPA_SUCCESS) {
225                                                   LogDebug("TPM_TerminateHandle returned %d", result);
226                                         }
227                               }
228                        /* clear the slot */
229                               auth_mgr.open_auth_sessions--;
230                               auth_mgr.auth_mapper[i].full = FALSE;
231                        auth_mgr.auth_mapper[i].tpm_handle = 0;
232                        auth_mgr.auth_mapper[i].tcs_ctx = 0;
233                               LogDebug("released auth for TCS %x TPM %x", tcs_handle,
234                                auth_mgr.auth_mapper[i].tpm_handle);
235 
236                               auth_mgr_swap_in();
237                     }
238           }
239 
240           return TSS_SUCCESS;
241 }
242 
243 void
auth_mgr_release_auth(TPM_AUTH * auth0,TPM_AUTH * auth1,TCS_CONTEXT_HANDLE tcs_handle)244 auth_mgr_release_auth(TPM_AUTH *auth0, TPM_AUTH *auth1, TCS_CONTEXT_HANDLE tcs_handle)
245 {
246           if (auth0)
247                     auth_mgr_release_auth_handle(auth0->AuthHandle, tcs_handle,
248                                                        auth0->fContinueAuthSession);
249 
250           if (auth1)
251                     auth_mgr_release_auth_handle(auth1->AuthHandle, tcs_handle,
252                                                        auth1->fContinueAuthSession);
253 }
254 
255 /* unload the auth ctx associated with this auth handle */
256 TSS_RESULT
auth_mgr_release_auth_handle(TCS_AUTHHANDLE tpm_auth_handle,TCS_CONTEXT_HANDLE tcs_handle,TSS_BOOL cont)257 auth_mgr_release_auth_handle(TCS_AUTHHANDLE tpm_auth_handle, TCS_CONTEXT_HANDLE tcs_handle,
258                                    TSS_BOOL cont)
259 {
260           UINT32 i;
261           TSS_RESULT result = TSS_SUCCESS;
262 
263           for (i = 0; i < auth_mgr.auth_mapper_size; i++) {
264                     if (auth_mgr.auth_mapper[i].full == TRUE &&
265                         auth_mgr.auth_mapper[i].tpm_handle == tpm_auth_handle &&
266                         auth_mgr.auth_mapper[i].tcs_ctx == tcs_handle) {
267                               if (!cont) {
268                                /*
269                                 * This function should not be necessary, but
270                                 * if the main operation resulted in an error,
271                                 * the TPM may still hold the auth handle
272                                 * and it must be freed.  Most of the time
273                                 * this call will result in TPM_E_INVALID_AUTHHANDLE
274                                 * error which can be ignored.
275                                 */
276                                result = TCSP_FlushSpecific_Common(
277                                    auth_mgr.auth_mapper[i].tpm_handle,
278                                    TPM_RT_AUTH);
279 
280                                         /* Ok, probably dealing with a 1.1 TPM */
281                                         if (result == TPM_E_BAD_ORDINAL)
282                                        result = internal_TerminateHandle(
283                                            auth_mgr.auth_mapper[i].tpm_handle);
284 
285                                         if (result == TCPA_E_INVALID_AUTHHANDLE) {
286                                                   LogDebug("Tried to close an invalid auth handle: %x",
287                                                              auth_mgr.auth_mapper[i].tpm_handle);
288                                         } else if (result != TCPA_SUCCESS) {
289                                                   LogDebug("TPM_TerminateHandle returned %d", result);
290                                         }
291 
292                                if (result == TPM_SUCCESS) {
293                                        LogDebug("released auth for TCS %x TPM %x",
294                                                 auth_mgr.auth_mapper[i].tcs_ctx, tpm_auth_handle);
295                                }
296                                /*
297                                 * Mark it as released, the "cont" flag indicates
298                                 * that it is no longer needed.
299                                 */
300                                auth_mgr.open_auth_sessions--;
301                                auth_mgr.auth_mapper[i].full = FALSE;
302                                auth_mgr.auth_mapper[i].tpm_handle = 0;
303                                auth_mgr.auth_mapper[i].tcs_ctx = 0;
304                                auth_mgr_swap_in();
305                               }
306                        /* If the cont flag is TRUE, we have to keep the handle */
307                     }
308           }
309 
310           return result;
311 }
312 
313 TSS_RESULT
auth_mgr_check(TCS_CONTEXT_HANDLE tcsContext,TPM_AUTHHANDLE * tpm_auth_handle)314 auth_mgr_check(TCS_CONTEXT_HANDLE tcsContext, TPM_AUTHHANDLE *tpm_auth_handle)
315 {
316           UINT32 i;
317           TSS_RESULT result = TSS_SUCCESS;
318 
319           for (i = 0; i < auth_mgr.auth_mapper_size; i++) {
320                     if (auth_mgr.auth_mapper[i].full == TRUE &&
321                         auth_mgr.auth_mapper[i].tpm_handle == *tpm_auth_handle &&
322                         auth_mgr.auth_mapper[i].tcs_ctx == tcsContext) {
323                               /* We have a record of this session, now swap it into the TPM if need be. */
324                               if (auth_mgr.auth_mapper[i].swap) {
325                                         LogDebugFn("TPM_LoadAuthContext for TCS %x TPM %x", tcsContext,
326                                                      auth_mgr.auth_mapper[i].tpm_handle);
327 
328                                         result = TPM_LoadAuthContext(auth_mgr.auth_mapper[i].swap_size,
329                                                                            auth_mgr.auth_mapper[i].swap,
330                                                                            tpm_auth_handle);
331                                         if (result == TSS_SUCCESS) {
332                                                   free(auth_mgr.auth_mapper[i].swap);
333                                                   auth_mgr.auth_mapper[i].swap = NULL;
334                                                   auth_mgr.auth_mapper[i].swap_size = 0;
335 
336                                                   LogDebugFn("TPM_LoadAuthContext succeeded. Old TPM: %x, New"
337                                                                " TPM: %x", auth_mgr.auth_mapper[i].tpm_handle,
338                                                                *tpm_auth_handle);
339 
340                                                   auth_mgr.auth_mapper[i].tpm_handle = *tpm_auth_handle;
341                                         } else if (result == TPM_E_RESOURCES) {
342                                                   if ((result = auth_mgr_swap_out(tcsContext))) {
343                                                             LogDebugFn("TPM_LoadAuthContext failed with TPM_E_R"
344                                                                          "ESOURCES and swapping out failed, retur"
345                                                                          "ning error");
346                                                             return result;
347                                                   }
348 
349                                                   LogDebugFn("Retrying TPM_LoadAuthContext after swap"
350                                                                " out...");
351                                                   result =
352                                                         TPM_LoadAuthContext(auth_mgr.auth_mapper[i].swap_size,
353                                                                                   auth_mgr.auth_mapper[i].swap,
354                                                                                   tpm_auth_handle);
355                                                   free(auth_mgr.auth_mapper[i].swap);
356                                                   auth_mgr.auth_mapper[i].swap = NULL;
357                                                   auth_mgr.auth_mapper[i].swap_size = 0;
358                                         } else {
359                                                   LogDebug("TPM_LoadAuthContext failed: 0x%x.", result);
360                                         }
361                               }
362 
363                               return result;
364                     }
365           }
366 
367           LogDebugFn("Can't find auth for TCS handle %x, should be %x", tcsContext, *tpm_auth_handle);
368           return TCSERR(TSS_E_INTERNAL_ERROR);
369 }
370 
371 TSS_RESULT
auth_mgr_add(TCS_CONTEXT_HANDLE tcsContext,TCS_AUTHHANDLE tpm_auth_handle)372 auth_mgr_add(TCS_CONTEXT_HANDLE tcsContext, TCS_AUTHHANDLE tpm_auth_handle)
373 {
374           struct auth_map *tmp = auth_mgr.auth_mapper;
375           UINT32 i;
376 
377           for (i = 0; i < auth_mgr.auth_mapper_size; i++) {
378                     if (auth_mgr.auth_mapper[i].full == FALSE) {
379                               auth_mgr.auth_mapper[i].tpm_handle = tpm_auth_handle;
380                               auth_mgr.auth_mapper[i].tcs_ctx = tcsContext;
381                               auth_mgr.auth_mapper[i].full = TRUE;
382                               auth_mgr.open_auth_sessions++;
383                               LogDebug("added auth for TCS %x TPM %x", tcsContext, tpm_auth_handle);
384 
385                               return TSS_SUCCESS;
386                     }
387           }
388 
389 
390           LogDebugFn("Thread %ld growing the auth table to %u entries", THREAD_ID,
391                        auth_mgr.auth_mapper_size + TSS_DEFAULT_AUTH_TABLE_SIZE);
392 
393           auth_mgr.auth_mapper = calloc(auth_mgr.auth_mapper_size +
394                                               TSS_DEFAULT_AUTH_TABLE_SIZE, sizeof(struct auth_map));
395           if (auth_mgr.auth_mapper == NULL) {
396                     auth_mgr.auth_mapper = tmp;
397                     return TCSERR(TSS_E_OUTOFMEMORY);
398           } else {
399                     memcpy(auth_mgr.auth_mapper, tmp,
400                                         auth_mgr.auth_mapper_size * sizeof(struct auth_map));
401                     auth_mgr.auth_mapper_size += TSS_DEFAULT_AUTH_TABLE_SIZE;
402                     LogDebugFn("Success.");
403                     return TSS_SUCCESS;
404           }
405 }
406 
407 /* A thread wants a new OIAP or OSAP session with the TPM. Returning TRUE indicates that we should
408  * allow it to open the session, FALSE to indicate that the request should be queued or have
409  * another thread's session swapped out to make room for it.
410  */
411 TSS_BOOL
auth_mgr_req_new(TCS_CONTEXT_HANDLE hContext)412 auth_mgr_req_new(TCS_CONTEXT_HANDLE hContext)
413 {
414           UINT32 i, opened = 0;
415 
416           for (i = 0; i < auth_mgr.auth_mapper_size; i++) {
417                     if (auth_mgr.auth_mapper[i].full == TRUE &&
418                         auth_mgr.auth_mapper[i].tcs_ctx  == hContext) {
419                               opened++;
420                     }
421           }
422 
423           /* If this TSP has already opened its max open auth handles, deny another open */
424           if (opened >= MAX(2, (UINT32)auth_mgr.max_auth_sessions/2)) {
425                     LogDebug("Max opened auth handles already opened.");
426                     return FALSE;
427           }
428 
429           /* if we have one opened already and there's a slot available, ok */
430           if (opened && ((auth_mgr.max_auth_sessions - auth_mgr.open_auth_sessions) >= 1))
431                     return TRUE;
432 
433           /* we don't already have one open and there are at least 2 slots left */
434           if ((auth_mgr.max_auth_sessions - auth_mgr.open_auth_sessions) >= 2)
435                     return TRUE;
436 
437           LogDebug("Request for new auth handle denied by TCS. (%d opened sessions)", opened);
438 
439           return FALSE;
440 }
441 
442 TSS_RESULT
auth_mgr_oiap(TCS_CONTEXT_HANDLE hContext,TCS_AUTHHANDLE * authHandle,TCPA_NONCE * nonce0)443 auth_mgr_oiap(TCS_CONTEXT_HANDLE hContext,        /* in */
444                 TCS_AUTHHANDLE *authHandle,       /* out */
445                 TCPA_NONCE *nonce0)               /* out */
446 {
447           TSS_RESULT result;
448 
449           /* are the maximum number of auth sessions open? */
450           if (auth_mgr_req_new(hContext) == FALSE) {
451                     if ((result = auth_mgr_swap_out(hContext)))
452                               goto done;
453           }
454 
455           if ((result = TCSP_OIAP_Internal(hContext, authHandle, nonce0)))
456                     goto done;
457 
458           /* success, add an entry to the table */
459           result = auth_mgr_add(hContext, *authHandle);
460 done:
461           return result;
462 }
463 
464 TSS_RESULT
auth_mgr_osap(TCS_CONTEXT_HANDLE hContext,TCPA_ENTITY_TYPE entityType,UINT32 entityValue,TCPA_NONCE nonceOddOSAP,TCS_AUTHHANDLE * authHandle,TCPA_NONCE * nonceEven,TCPA_NONCE * nonceEvenOSAP)465 auth_mgr_osap(TCS_CONTEXT_HANDLE hContext,        /* in */
466                 TCPA_ENTITY_TYPE entityType,      /* in */
467                 UINT32 entityValue,               /* in */
468                 TCPA_NONCE nonceOddOSAP,                    /* in */
469                 TCS_AUTHHANDLE *authHandle,       /* out */
470                 TCPA_NONCE *nonceEven,            /* out */
471                 TCPA_NONCE *nonceEvenOSAP)        /* out */
472 {
473           TSS_RESULT result;
474           UINT32 newEntValue = 0;
475 
476           /* if ET is not KEYHANDLE or KEY, newEntValue is a don't care */
477           if (entityType == TCPA_ET_KEYHANDLE || entityType == TCPA_ET_KEY) {
478                     if (ensureKeyIsLoaded(hContext, entityValue, &newEntValue))
479                               return TCSERR(TSS_E_FAIL);
480           } else {
481                     newEntValue = entityValue;
482           }
483 
484           /* are the maximum number of auth sessions open? */
485           if (auth_mgr_req_new(hContext) == FALSE) {
486                     if ((result = auth_mgr_swap_out(hContext)))
487                               goto done;
488           }
489 
490           if ((result = TCSP_OSAP_Internal(hContext, entityType, newEntValue, nonceOddOSAP,
491                                                    authHandle, nonceEven, nonceEvenOSAP)))
492                     goto done;
493 
494           /* success, add an entry to the table */
495           result = auth_mgr_add(hContext, *authHandle);
496 done:
497           return result;
498 }
499 
500 /* This function is only called directly from the TSP, we use other internal routines to free
501  * our handles. */
502 TSS_RESULT
TCSP_TerminateHandle_Internal(TCS_CONTEXT_HANDLE hContext,TCS_AUTHHANDLE handle)503 TCSP_TerminateHandle_Internal(TCS_CONTEXT_HANDLE hContext,  /* in */
504                                     TCS_AUTHHANDLE handle)  /* in */
505 {
506           TSS_RESULT result;
507 
508           LogDebug("Entering TCSI_TerminateHandle");
509           if ((result = ctx_verify_context(hContext)))
510                     return result;
511 
512           if ((result = auth_mgr_check(hContext, &handle)))
513                     return result;
514 
515           result = auth_mgr_release_auth_handle(handle, hContext, TRUE);
516 
517           LogResult("Terminate Handle", result);
518           return result;
519 }
520 
521 TSS_RESULT
TPM_SaveAuthContext(TPM_AUTHHANDLE handle,UINT32 * size,BYTE ** blob)522 TPM_SaveAuthContext(TPM_AUTHHANDLE handle, UINT32 *size, BYTE **blob)
523 {
524           UINT64 offset;
525           UINT32 trash, bsize;
526           TSS_RESULT result;
527           BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
528 
529           offset = 10;
530           LoadBlob_UINT32(&offset, handle, txBlob);
531           LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_SaveAuthContext, txBlob);
532 
533           if ((result = req_mgr_submit_req(txBlob)))
534                     return result;
535 
536           result = UnloadBlob_Header(txBlob, &trash);
537 
538           LogDebug("total packet size received from TPM: %u", trash);
539 
540           if (!result) {
541                     offset = 10;
542                     UnloadBlob_UINT32(&offset, &bsize, txBlob);
543 
544                     LogDebug("Reported blob size from TPM: %u", bsize);
545 
546                     *blob = malloc(bsize);
547                     if (*blob == NULL) {
548                               LogError("malloc of %u bytes failed.", bsize);
549                               return TCSERR(TSS_E_OUTOFMEMORY);
550                     }
551                     UnloadBlob(&offset, bsize, txBlob, *blob);
552                     *size = bsize;
553           }
554 
555           return result;
556 }
557 
558 TSS_RESULT
TPM_LoadAuthContext(UINT32 size,BYTE * blob,TPM_AUTHHANDLE * handle)559 TPM_LoadAuthContext(UINT32 size, BYTE *blob, TPM_AUTHHANDLE *handle)
560 {
561           UINT64 offset;
562           UINT32 trash;
563           TSS_RESULT result;
564           BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
565 
566           LogDebugFn("Loading %u byte auth blob back into TPM", size);
567 
568           offset = 10;
569           LoadBlob_UINT32(&offset, size, txBlob);
570           LoadBlob(&offset, size, txBlob, blob);
571           LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_LoadAuthContext, txBlob);
572 
573           if ((result = req_mgr_submit_req(txBlob)))
574                     return result;
575 
576           result = UnloadBlob_Header(txBlob, &trash);
577 
578           if (!result) {
579                     offset = 10;
580                     UnloadBlob_UINT32(&offset, handle, txBlob);
581           }
582 
583           return result;
584 }
585