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 %ld, 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 %ld 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 %ld 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