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. 2005, 2007
8 *
9 */
10
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include <string.h>
16 #include <assert.h>
17
18 #include "trousers/tss.h"
19 #include "trousers/trousers.h"
20 #include "tcs_tsp.h"
21 #include "trousers_types.h"
22 #include "spi_utils.h"
23 #include "capabilities.h"
24 #include "tsplog.h"
25 #include "obj.h"
26 #include "tsp_tcsi_param.h"
27
28 TSS_RESULT
obj_context_add(TSS_HOBJECT * phObject)29 obj_context_add(TSS_HOBJECT *phObject)
30 {
31 TSS_RESULT result;
32 struct tr_context_obj *context = calloc(1, sizeof(struct tr_context_obj));
33
34 if (context == NULL) {
35 LogError("malloc of %zd bytes failed.", sizeof(struct tr_context_obj));
36 return TSPERR(TSS_E_OUTOFMEMORY);
37 }
38
39 #ifndef TSS_NO_GUI
40 context->silentMode = TSS_TSPATTRIB_CONTEXT_NOT_SILENT;
41 #else
42 context->silentMode = TSS_TSPATTRIB_CONTEXT_SILENT;
43 #endif
44 if ((result = get_tcsd_hostname((char **)&context->machineName,
45 &context->machineNameLength)) != TSS_SUCCESS) {
46 free(context);
47 return result;
48 }
49
50 LogDebug("Hostname to be used by the context is %s.", context->machineName);
51
52 context->hashMode = TSS_TSPATTRIB_HASH_MODE_NOT_NULL;
53 context->connection_policy = TSS_TSPATTRIB_CONTEXT_VERSION_V1_1;
54
55 if ((result = obj_list_add(&context_list, NULL_HCONTEXT, 0, context, phObject))) {
56 free(context->machineName);
57 free(context);
58 return result;
59 }
60
61 /* Add the default policy */
62 if ((result = obj_policy_add(*phObject, TSS_POLICY_USAGE, &context->policy))) {
63 obj_list_remove(&context_list, &__tspi_obj_context_free, *phObject, *phObject);
64 return result;
65 }
66
67 context->tcs_api = &tcs_normal_api;
68
69 return TSS_SUCCESS;
70 }
71
72 struct tcs_api_table *
obj_context_get_tcs_api(TSS_HCONTEXT tspContext)73 obj_context_get_tcs_api(TSS_HCONTEXT tspContext)
74 {
75 struct tsp_object *obj;
76 struct tr_context_obj *context;
77 struct tcs_api_table *t;
78
79 /* If the object cannot be found with the given handle, return a safe value, the normal TCS
80 * API pointer. Since the handle is bad, the RPC_ function will barf in looking up the
81 * corresponding TCS context handle and an invalid handle error will be returned. */
82 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
83 return &tcs_normal_api;
84
85 context = (struct tr_context_obj *)obj->data;
86
87 /* Return the current API set we're using, either the normal API, or the transport encrypted
88 * API. The context->tcs_api variable is switched back and forth between the two sets by
89 * the obj_context_transport_set_control function through a set attrib. */
90 t = context->tcs_api;
91
92 obj_list_put(&context_list);
93
94 return t;
95 }
96
97 void
__tspi_obj_context_free(void * data)98 __tspi_obj_context_free(void *data)
99 {
100 struct tr_context_obj *context = (struct tr_context_obj *)data;
101
102 free(context->machineName);
103 free(context);
104 }
105
106 TSS_BOOL
obj_is_context(TSS_HOBJECT hObject)107 obj_is_context(TSS_HOBJECT hObject)
108 {
109 TSS_BOOL answer = FALSE;
110
111 if ((obj_list_get_obj(&context_list, hObject))) {
112 answer = TRUE;
113 obj_list_put(&context_list);
114 }
115
116 return answer;
117 }
118
119 /* Clean up transport session if necessary. */
120 void
obj_context_close(TSS_HCONTEXT tspContext)121 obj_context_close(TSS_HCONTEXT tspContext)
122 {
123 struct tsp_object *obj;
124 struct tr_context_obj *context;
125
126 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
127 return;
128
129 context = (struct tr_context_obj *)obj->data;
130
131 #ifdef TSS_BUILD_TRANSPORT
132 if (context->transAuth.AuthHandle) {
133 RPC_FlushSpecific(tspContext, context->transAuth.AuthHandle, TPM_RT_TRANS);
134
135 __tspi_memset(&context->transPub, 0, sizeof(TPM_TRANSPORT_PUBLIC));
136 __tspi_memset(&context->transMod, 0, sizeof(TPM_MODIFIER_INDICATOR));
137 __tspi_memset(&context->transSecret, 0, sizeof(TPM_TRANSPORT_AUTH));
138 __tspi_memset(&context->transAuth, 0, sizeof(TPM_AUTH));
139 __tspi_memset(&context->transLogIn, 0, sizeof(TPM_TRANSPORT_LOG_IN));
140 __tspi_memset(&context->transLogOut, 0, sizeof(TPM_TRANSPORT_LOG_OUT));
141 __tspi_memset(&context->transLogDigest, 0, sizeof(TPM_DIGEST));
142 }
143 #endif
144
145 obj_list_put(&context_list);
146 }
147
148 TSS_RESULT
obj_context_get_policy(TSS_HCONTEXT tspContext,UINT32 policyType,TSS_HPOLICY * phPolicy)149 obj_context_get_policy(TSS_HCONTEXT tspContext, UINT32 policyType, TSS_HPOLICY *phPolicy)
150 {
151 struct tsp_object *obj;
152 struct tr_context_obj *context;
153 TSS_RESULT result = TSS_SUCCESS;
154
155 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
156 return TSPERR(TSS_E_INVALID_HANDLE);
157
158 context = (struct tr_context_obj *)obj->data;
159
160 switch (policyType) {
161 case TSS_POLICY_USAGE:
162 *phPolicy = context->policy;
163 break;
164 default:
165 result = TSPERR(TSS_E_BAD_PARAMETER);
166 }
167
168 obj_list_put(&context_list);
169
170 return result;
171 }
172
173 TSS_RESULT
obj_context_get_machine_name(TSS_HCONTEXT tspContext,UINT32 * size,BYTE ** data)174 obj_context_get_machine_name(TSS_HCONTEXT tspContext, UINT32 *size, BYTE **data)
175 {
176 struct tsp_object *obj;
177 struct tr_context_obj *context;
178 TSS_RESULT result;
179
180 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
181 return TSPERR(TSS_E_INVALID_HANDLE);
182
183 context = (struct tr_context_obj *)obj->data;
184
185 if (context->machineNameLength == 0) {
186 *data = NULL;
187 *size = 0;
188 LogDebug("context->machineName is NULL.");
189 } else {
190 /*
191 * Don't use calloc_tspi because this memory is
192 * not freed using "free_tspi"
193 */
194 *data = calloc(1, context->machineNameLength);
195 if (*data == NULL) {
196 LogError("malloc of %u bytes failed.",
197 context->machineNameLength);
198 result = TSPERR(TSS_E_OUTOFMEMORY);
199 goto done;
200 }
201 *size = context->machineNameLength;
202 LogDebug("context->machineName: %s.", context->machineName);
203 memcpy(*data, context->machineName, *size);
204 }
205
206 result = TSS_SUCCESS;
207
208 done:
209 obj_list_put(&context_list);
210
211 return result;
212 }
213
214 /* This function converts the machine name to a TSS_UNICODE string before
215 * returning it, as Tspi_GetAttribData would like. We could do the conversion
216 * in Tspi_GetAttribData, but we don't have access to the TSP context there */
217 TSS_RESULT
obj_context_get_machine_name_attrib(TSS_HCONTEXT tspContext,UINT32 * size,BYTE ** data)218 obj_context_get_machine_name_attrib(TSS_HCONTEXT tspContext, UINT32 *size, BYTE **data)
219 {
220 struct tsp_object *obj;
221 struct tr_context_obj *context;
222 BYTE *utf_string;
223 UINT32 utf_size;
224 TSS_RESULT result;
225
226 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
227 return TSPERR(TSS_E_INVALID_HANDLE);
228
229 context = (struct tr_context_obj *)obj->data;
230
231 if (context->machineNameLength == 0) {
232 *data = NULL;
233 *size = 0;
234 } else {
235 utf_size = context->machineNameLength;
236 utf_string = Trspi_Native_To_UNICODE(context->machineName,
237 &utf_size);
238 if (utf_string == NULL) {
239 result = TSPERR(TSS_E_INTERNAL_ERROR);
240 goto done;
241 }
242
243 *data = calloc_tspi(obj->tspContext, utf_size);
244 if (*data == NULL) {
245 free(utf_string);
246 LogError("malloc of %u bytes failed.", utf_size);
247 result = TSPERR(TSS_E_OUTOFMEMORY);
248 goto done;
249 }
250 *size = utf_size;
251 memcpy(*data, utf_string, utf_size);
252 free(utf_string);
253 }
254
255 result = TSS_SUCCESS;
256
257 done:
258 obj_list_put(&context_list);
259
260 return result;
261 }
262
263 TSS_RESULT
obj_context_set_machine_name(TSS_HCONTEXT tspContext,BYTE * name,UINT32 len)264 obj_context_set_machine_name(TSS_HCONTEXT tspContext, BYTE *name, UINT32 len)
265 {
266 struct tsp_object *obj;
267 struct tr_context_obj *context;
268
269 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
270 return TSPERR(TSS_E_INVALID_HANDLE);
271
272 context = (struct tr_context_obj *)obj->data;
273
274 free(context->machineName);
275
276 context->machineName = (BYTE *)calloc(1, len);
277 if (context->machineName == NULL) {
278 LogError("malloc of %u bytes failed.", len);
279 return TSPERR(TSS_E_OUTOFMEMORY);
280 }
281 memcpy(context->machineName, name, len);
282
283 context->machineNameLength = len;
284
285 obj_list_put(&context_list);
286
287 return TSS_SUCCESS;
288 }
289
290 TSS_BOOL
obj_context_is_silent(TSS_HCONTEXT tspContext)291 obj_context_is_silent(TSS_HCONTEXT tspContext)
292 {
293 struct tsp_object *obj;
294 struct tr_context_obj *context;
295 TSS_BOOL silent = FALSE;
296
297 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
298 return FALSE;
299
300 context = (struct tr_context_obj *)obj->data;
301 if (context->silentMode == TSS_TSPATTRIB_CONTEXT_SILENT)
302 silent = TRUE;
303
304 obj_list_put(&context_list);
305
306 return silent;
307 }
308
309 TSS_RESULT
obj_context_get_mode(TSS_HCONTEXT tspContext,UINT32 * mode)310 obj_context_get_mode(TSS_HCONTEXT tspContext, UINT32 *mode)
311 {
312 struct tsp_object *obj;
313 struct tr_context_obj *context;
314
315 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
316 return TSPERR(TSS_E_INVALID_HANDLE);
317
318 context = (struct tr_context_obj *)obj->data;
319 *mode = context->silentMode;
320
321 obj_list_put(&context_list);
322
323 return TSS_SUCCESS;
324 }
325
326 TSS_RESULT
obj_context_set_mode(TSS_HCONTEXT tspContext,UINT32 mode)327 obj_context_set_mode(TSS_HCONTEXT tspContext, UINT32 mode)
328 {
329 struct tsp_object *obj;
330 struct tr_context_obj *context;
331
332 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
333 return TSPERR(TSS_E_INVALID_HANDLE);
334
335 context = (struct tr_context_obj *)obj->data;
336 context->silentMode = mode;
337
338 obj_list_put(&context_list);
339
340 return TSS_SUCCESS;
341 }
342
343 /* search the list of all policies bound to context @tspContext. If
344 * one is found of type popup, return TRUE, else return FALSE. */
345 TSS_BOOL
obj_context_has_popups(TSS_HCONTEXT tspContext)346 obj_context_has_popups(TSS_HCONTEXT tspContext)
347 {
348 struct tsp_object *obj;
349 struct tr_policy_obj *policy;
350 struct obj_list *list = &policy_list;
351 TSS_BOOL ret = FALSE;
352
353 MUTEX_LOCK(list->lock);
354
355 for (obj = list->head; obj; obj = obj->next) {
356 if (obj->tspContext == tspContext) {
357 policy = (struct tr_policy_obj *)obj->data;
358 if (policy->SecretMode == TSS_SECRET_MODE_POPUP)
359 ret = TRUE;
360 break;
361 }
362 }
363
364 MUTEX_UNLOCK(list->lock);
365
366 return ret;
367 }
368
369 TSS_RESULT
obj_context_get_hash_mode(TSS_HCONTEXT tspContext,UINT32 * mode)370 obj_context_get_hash_mode(TSS_HCONTEXT tspContext, UINT32 *mode)
371 {
372 struct tsp_object *obj;
373 struct tr_context_obj *context;
374
375 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
376 return TSPERR(TSS_E_INVALID_HANDLE);
377
378 context = (struct tr_context_obj *)obj->data;
379 *mode = context->hashMode;
380
381 obj_list_put(&context_list);
382
383 return TSS_SUCCESS;
384 }
385
386 TSS_RESULT
obj_context_set_hash_mode(TSS_HCONTEXT tspContext,UINT32 mode)387 obj_context_set_hash_mode(TSS_HCONTEXT tspContext, UINT32 mode)
388 {
389 struct tsp_object *obj;
390 struct tr_context_obj *context;
391
392 switch (mode) {
393 case TSS_TSPATTRIB_HASH_MODE_NULL:
394 case TSS_TSPATTRIB_HASH_MODE_NOT_NULL:
395 break;
396 default:
397 return TSPERR(TSS_E_INVALID_ATTRIB_DATA);
398 }
399
400 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
401 return TSPERR(TSS_E_INVALID_HANDLE);
402
403 context = (struct tr_context_obj *)obj->data;
404 context->hashMode = mode;
405
406 obj_list_put(&context_list);
407
408 return TSS_SUCCESS;
409 }
410
411 TSS_RESULT
obj_context_get_connection_version(TSS_HCONTEXT tspContext,UINT32 * version)412 obj_context_get_connection_version(TSS_HCONTEXT tspContext, UINT32 *version)
413 {
414 struct tsp_object *obj;
415 struct tr_context_obj *context;
416
417 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
418 return TSPERR(TSS_E_INVALID_HANDLE);
419
420 context = (struct tr_context_obj *)obj->data;
421
422 *version = context->current_connection;
423
424 obj_list_put(&context_list);
425
426 return TSS_SUCCESS;
427 }
428
429 TSS_RESULT
obj_context_set_connection_policy(TSS_HCONTEXT tspContext,UINT32 policy)430 obj_context_set_connection_policy(TSS_HCONTEXT tspContext, UINT32 policy)
431 {
432 struct tsp_object *obj;
433 struct tr_context_obj *context;
434
435 switch (policy) {
436 case TSS_TSPATTRIB_CONTEXT_VERSION_V1_1:
437 case TSS_TSPATTRIB_CONTEXT_VERSION_V1_2:
438 case TSS_TSPATTRIB_CONTEXT_VERSION_AUTO:
439 break;
440 default:
441 return TSPERR(TSS_E_INVALID_ATTRIB_DATA);
442 }
443
444 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
445 return TSPERR(TSS_E_INVALID_HANDLE);
446
447 context = (struct tr_context_obj *)obj->data;
448
449 context->connection_policy = policy;
450
451 obj_list_put(&context_list);
452
453 return TSS_SUCCESS;
454 }
455
456 #ifdef TSS_BUILD_TRANSPORT
457 TSS_RESULT
obj_context_set_transport_key(TSS_HCONTEXT tspContext,TSS_HKEY hKey)458 obj_context_set_transport_key(TSS_HCONTEXT tspContext, TSS_HKEY hKey)
459 {
460 struct tsp_object *obj;
461 struct tr_context_obj *context;
462
463 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
464 return TSPERR(TSS_E_INVALID_HANDLE);
465
466 context = (struct tr_context_obj *)obj->data;
467
468 context->transKey = hKey;
469
470 obj_list_put(&context_list);
471
472 return TSS_SUCCESS;
473 }
474
475 TSS_RESULT
obj_context_transport_get_mode(TSS_HCONTEXT tspContext,UINT32 value,UINT32 * out)476 obj_context_transport_get_mode(TSS_HCONTEXT tspContext, UINT32 value, UINT32 *out)
477 {
478 TSS_RESULT result = TSS_SUCCESS;
479 struct tsp_object *obj;
480 struct tr_context_obj *context;
481
482 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
483 return TSPERR(TSS_E_INVALID_HANDLE);
484
485 context = (struct tr_context_obj *)obj->data;
486
487 switch (value) {
488 case TSS_TSPATTRIB_TRANSPORT_NO_DEFAULT_ENCRYPTION:
489 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT ?
490 FALSE : TRUE;
491 break;
492 case TSS_TSPATTRIB_TRANSPORT_DEFAULT_ENCRYPTION:
493 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT ?
494 TRUE : FALSE;
495 break;
496 case TSS_TSPATTRIB_TRANSPORT_AUTHENTIC_CHANNEL:
497 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC ?
498 TRUE : FALSE;
499 break;
500 case TSS_TSPATTRIB_TRANSPORT_EXCLUSIVE:
501 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_EXCLUSIVE ?
502 TRUE : FALSE;
503 break;
504 case TSS_TSPATTRIB_TRANSPORT_STATIC_AUTH:
505 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_STATIC_AUTH ?
506 TRUE : FALSE;
507 break;
508 default:
509 LogError("Invalid attribute subflag: 0x%x", value);
510 result = TSPERR(TSS_E_INVALID_ATTRIB_SUBFLAG);
511 break;
512 }
513
514 obj_list_put(&context_list);
515
516 return result;
517 }
518
519 TSS_RESULT
obj_context_transport_get_control(TSS_HCONTEXT tspContext,UINT32 value,UINT32 * out)520 obj_context_transport_get_control(TSS_HCONTEXT tspContext, UINT32 value, UINT32 *out)
521 {
522 TSS_RESULT result = TSS_SUCCESS;
523 struct tsp_object *obj;
524 struct tr_context_obj *context;
525
526 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
527 return TSPERR(TSS_E_INVALID_HANDLE);
528
529 context = (struct tr_context_obj *)obj->data;
530
531 switch (value) {
532 case TSS_TSPATTRIB_DISABLE_TRANSPORT:
533 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED ? FALSE : TRUE;
534 break;
535 case TSS_TSPATTRIB_ENABLE_TRANSPORT:
536 *out = context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED ? TRUE : FALSE;
537 break;
538 default:
539 LogError("Invalid attribute subflag: 0x%x", value);
540 result = TSPERR(TSS_E_INVALID_ATTRIB_SUBFLAG);
541 break;
542 }
543
544 obj_list_put(&context_list);
545
546 return result;
547 }
548
549 TSS_RESULT
obj_context_transport_set_control(TSS_HCONTEXT tspContext,UINT32 value)550 obj_context_transport_set_control(TSS_HCONTEXT tspContext, UINT32 value)
551 {
552 TSS_RESULT result = TSS_SUCCESS;
553 struct tsp_object *obj;
554 struct tr_context_obj *context;
555
556 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
557 return TSPERR(TSS_E_INVALID_HANDLE);
558
559 context = (struct tr_context_obj *)obj->data;
560
561 switch (value) {
562 case TSS_TSPATTRIB_ENABLE_TRANSPORT:
563 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED;
564 context->tcs_api = &tcs_transport_api;
565 break;
566 case TSS_TSPATTRIB_DISABLE_TRANSPORT:
567 context->flags &= ~TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED;
568 context->tcs_api = &tcs_normal_api;
569 break;
570 default:
571 LogError("Invalid attribute subflag: 0x%x", value);
572 result = TSPERR(TSS_E_INTERNAL_ERROR);
573 break;
574 }
575
576 obj_list_put(&context_list);
577
578 return result;
579 }
580
581 TSS_RESULT
obj_context_transport_set_mode(TSS_HCONTEXT tspContext,UINT32 value)582 obj_context_transport_set_mode(TSS_HCONTEXT tspContext, UINT32 value)
583 {
584 TSS_RESULT result = TSS_SUCCESS;
585 struct tsp_object *obj;
586 struct tr_context_obj *context;
587
588 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
589 return TSPERR(TSS_E_INVALID_HANDLE);
590
591 context = (struct tr_context_obj *)obj->data;
592
593 switch (value) {
594 case TSS_TSPATTRIB_TRANSPORT_NO_DEFAULT_ENCRYPTION:
595 context->flags &= ~TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT;
596 break;
597 case TSS_TSPATTRIB_TRANSPORT_DEFAULT_ENCRYPTION:
598 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT;
599 break;
600 case TSS_TSPATTRIB_TRANSPORT_AUTHENTIC_CHANNEL:
601 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC;
602 break;
603 case TSS_TSPATTRIB_TRANSPORT_EXCLUSIVE:
604 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_EXCLUSIVE;
605 break;
606 case TSS_TSPATTRIB_TRANSPORT_STATIC_AUTH:
607 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_STATIC_AUTH;
608 break;
609 default:
610 LogError("Invalid attribute subflag: 0x%x", value);
611 result = TSPERR(TSS_E_INTERNAL_ERROR);
612 break;
613 }
614
615 obj_list_put(&context_list);
616
617 return result;
618 }
619
620 #if 0
621 TSS_RESULT
622 get_trans_props(TSS_HCONTEXT tspContext, UINT32 *alg, UINT16 *enc)
623 {
624 TSS_RESULT result;
625 UINT32 algs[] = { TPM_ALG_MGF1, TPM_ALG_AES128, 0 }, a = 0;
626 UINT16 encs[] = { TPM_ES_SYM_OFB, TPM_ES_SYM_CNT, TPM_ES_SYM_CBC_PKCS5PAD, 0 }, e = 0;
627 BYTE *respData;
628 UINT32 respLen, tcsSubCap32;
629 UINT16 tcsSubCap16;
630
631 if (*alg)
632 goto check_es;
633
634 for (a = 0; algs[a]; a++) {
635 tcsSubCap32 = endian32(algs[a]);
636
637 if ((result = RPC_GetTPMCapability(tspContext, TPM_CAP_TRANS_ALG, sizeof(UINT32),
638 (BYTE *)&tcsSubCap32, &respLen, &respData)))
639 return result;
640
641 if (*(TSS_BOOL *)respData == TRUE) {
642 free(respData);
643 break;
644 }
645 free(respData);
646 }
647
648 if (!algs[a]) {
649 LogError("TPM reports no usable sym algorithms for transport session");
650 return TSPERR(TSS_E_INTERNAL_ERROR);
651 }
652
653 check_es:
654 if (*enc || algs[a] == TPM_ALG_MGF1)
655 goto done;
656
657 for (e = 0; encs[e]; e++) {
658 tcsSubCap16 = endian16(encs[e]);
659
660 if ((result = RPC_GetTPMCapability(tspContext, TPM_CAP_TRANS_ES, sizeof(UINT16),
661 (BYTE *)&tcsSubCap16, &respLen, &respData)))
662 return result;
663
664 if (*(TSS_BOOL *)respData == TRUE) {
665 free(respData);
666 break;
667 }
668 free(respData);
669 }
670
671 if (!encs[e]) {
672 LogError("TPM reports no usable sym modes for transport session");
673 return TSPERR(TSS_E_INTERNAL_ERROR);
674 }
675
676 *alg = algs[a];
677 *enc = encs[e];
678 done:
679 return TSS_SUCCESS;
680 }
681 #endif
682
683 /* called before each TCSP_ExecuteTransport call */
684 TSS_RESULT
obj_context_transport_init(TSS_HCONTEXT tspContext)685 obj_context_transport_init(TSS_HCONTEXT tspContext)
686 {
687 TSS_RESULT result = TSS_SUCCESS;
688 struct tsp_object *obj;
689 struct tr_context_obj *context;
690
691 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
692 return TSPERR(TSS_E_INVALID_HANDLE);
693
694 context = (struct tr_context_obj *)obj->data;
695
696 /* return immediately if we're not in a transport session */
697 if (!(context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED)) {
698 result = TSPERR(TSS_E_INTERNAL_ERROR);
699 goto done;
700 }
701
702 /* if the session is not yet established, setup and call EstablishTransport */
703 if (!(context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_ESTABLISHED)) {
704 if ((result = obj_context_transport_establish(tspContext, context)))
705 goto done;
706 }
707
708 context->flags |= TSS_CONTEXT_FLAGS_TRANSPORT_ESTABLISHED;
709
710 result = TSS_SUCCESS;
711 done:
712 obj_list_put(&context_list);
713
714 return result;
715 }
716
717 TSS_RESULT
obj_context_transport_establish(TSS_HCONTEXT tspContext,struct tr_context_obj * context)718 obj_context_transport_establish(TSS_HCONTEXT tspContext, struct tr_context_obj *context)
719 {
720 TSS_RESULT result;
721 UINT32 tickLen, secretLen, transPubLen, exclusive = TSS_TCSATTRIB_TRANSPORT_DEFAULT;
722 BYTE *ticks, *secret;
723 UINT64 offset;
724 Trspi_HashCtx hashCtx;
725 TPM_DIGEST digest;
726 TSS_HPOLICY hTransKeyPolicy;
727 TPM_AUTH auth, *pAuth, *pTransAuth;
728 TCS_KEY_HANDLE tcsTransKey;
729 TSS_BOOL usesAuth = FALSE;
730 UINT32 encKeyLen;
731 BYTE encKey[256];
732 BYTE transPubBlob[sizeof(TPM_TRANSPORT_PUBLIC)];
733 BYTE transAuthBlob[sizeof(TPM_TRANSPORT_AUTH)];
734
735
736 context->transPub.tag = TPM_TAG_TRANSPORT_PUBLIC;
737 context->transSecret.tag = TPM_TAG_TRANSPORT_AUTH;
738
739 if ((result = get_local_random(tspContext, FALSE, TPM_SHA1_160_HASH_LEN,
740 (BYTE **)context->transSecret.authData.authdata)))
741 return result;
742
743 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_STATIC_AUTH)
744 context->transKey = TPM_KH_TRANSPORT;
745
746 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC)
747 context->transPub.transAttributes |= TPM_TRANSPORT_LOG;
748
749 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_EXCLUSIVE) {
750 context->transPub.transAttributes |= TPM_TRANSPORT_EXCLUSIVE;
751 exclusive = TSS_TCSATTRIB_TRANSPORT_EXCLUSIVE;
752 }
753
754 /* XXX implement AES128+CTR (Winbond, Infineon), then AES256+CTR (Atmel) */
755 context->transPub.algId = TPM_ALG_MGF1;
756 context->transPub.encScheme = TPM_ES_NONE;
757
758 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT) {
759 context->transPub.transAttributes |= TPM_TRANSPORT_ENCRYPT;
760
761 if (context->transKey == TPM_KH_TRANSPORT) {
762 LogError("No transport key handle has been set yet. Use "
763 "Tspi_Context_SetTransEncryptionKey to set this handle");
764 return TSPERR(TSS_E_INTERNAL_ERROR);
765 }
766 }
767
768 if (context->transKey == TPM_KH_TRANSPORT) {
769 secret = context->transSecret.authData.authdata;
770 secretLen = TPM_SHA1_160_HASH_LEN;
771 } else {
772 offset = 0;
773 Trspi_LoadBlob_TRANSPORT_AUTH(&offset, transAuthBlob, &context->transSecret);
774 secretLen = offset;
775
776 /* encrypt the sym key with the wrapping RSA key */
777 encKeyLen = sizeof(encKey);
778 if ((result = __tspi_rsa_encrypt(context->transKey, secretLen, transAuthBlob, &encKeyLen,
779 encKey)))
780 return result;
781
782 secret = encKey;
783 secretLen = encKeyLen;
784 }
785
786 offset = 0;
787 Trspi_LoadBlob_TRANSPORT_PUBLIC(&offset, transPubBlob, &context->transPub);
788 transPubLen = offset;
789
790 if (context->transKey != TPM_KH_TRANSPORT) {
791 if ((result = obj_rsakey_get_tcs_handle(context->transKey, &tcsTransKey)))
792 return result;
793
794 if ((result = obj_rsakey_get_policy(context->transKey, TSS_POLICY_USAGE,
795 &hTransKeyPolicy, &usesAuth)))
796 return result;
797
798 if (!usesAuth) {
799 LogError("Key used to establish a transport session must use auth");
800 return TSPERR(TSS_E_TSP_TRANS_AUTHREQUIRED);
801 }
802 } else
803 tcsTransKey = TPM_KH_TRANSPORT;
804
805 /* If logging is on, do TPM commands spec rev106 step 8.a */
806 __tspi_memset(context->transLogDigest.digest, 0, sizeof(TPM_DIGEST));
807 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) {
808 context->transLogIn.tag = TPM_TAG_TRANSPORT_LOG_IN;
809
810 /* step 8.a, i */
811 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
812 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_EstablishTransport);
813 result |= Trspi_HashUpdate(&hashCtx, transPubLen, transPubBlob);
814 result |= Trspi_Hash_UINT32(&hashCtx, secretLen);
815 result |= Trspi_HashUpdate(&hashCtx, secretLen, secret);
816 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogIn.parameters.digest)))
817 return result;
818
819 /* step 8.a, ii */
820 __tspi_memset(context->transLogIn.pubKeyHash.digest, 0, sizeof(TPM_DIGEST));
821
822 /* step 8.a, iii */
823 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
824 result |= Trspi_Hash_DIGEST(&hashCtx, context->transLogDigest.digest);
825 result |= Trspi_Hash_TRANSPORT_LOG_IN(&hashCtx, &context->transLogIn);
826 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogDigest.digest)))
827 return result;
828 }
829
830 if (usesAuth) {
831 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
832 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_EstablishTransport);
833 result |= Trspi_HashUpdate(&hashCtx, (UINT32)offset, (BYTE *)transPubBlob);
834 result |= Trspi_Hash_UINT32(&hashCtx, secretLen);
835 result |= Trspi_HashUpdate(&hashCtx, secretLen, secret);
836 if ((result |= Trspi_HashFinal(&hashCtx, (BYTE *)&digest)))
837 return result;
838
839 /* open OIAP session with continueAuthSession = TRUE */
840 if ((result = secret_PerformAuth_OIAP(context->transKey, TPM_ORD_EstablishTransport,
841 hTransKeyPolicy, TRUE, &digest, &auth)))
842 return result;
843
844 pAuth = &auth;
845 } else
846 pAuth = NULL;
847
848 result = RPC_EstablishTransport(tspContext, exclusive, tcsTransKey, transPubLen,
849 transPubBlob, secretLen, secret, pAuth, &context->transMod,
850 &context->transAuth.AuthHandle, &tickLen, &ticks,
851 &context->transAuth.NonceEven);
852 if (result) {
853 LogError("Establish Transport command failed: %s", Trspi_Error_String(result));
854 return result;
855 }
856
857 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
858 result |= Trspi_Hash_UINT32(&hashCtx, result);
859 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_EstablishTransport);
860 result |= Trspi_Hash_UINT32(&hashCtx, context->transMod);
861 result |= Trspi_HashUpdate(&hashCtx, tickLen, ticks);
862 result |= Trspi_Hash_NONCE(&hashCtx, context->transAuth.NonceEven.nonce);
863 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
864 return result;
865
866 if (usesAuth) {
867 if ((result = obj_policy_validate_auth_oiap(hTransKeyPolicy, &digest, pAuth)))
868 return result;
869 }
870
871 /* step 8.b iii */
872 offset = 0;
873 Trspi_UnloadBlob_CURRENT_TICKS(&offset, ticks, &context->transLogOut.currentTicks);
874 free(ticks);
875
876 /* If logging is on, do TPM commands spec rev106 step 8.b */
877 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) {
878 context->transLogOut.tag = TPM_TAG_TRANSPORT_LOG_OUT;
879
880 /* step 8.b i */
881 memcpy(context->transLogOut.parameters.digest, digest.digest, sizeof(TPM_DIGEST));
882
883 /* step 8.b ii */
884 context->transLogOut.locality = context->transMod;
885
886 /* step 8.b iii was done above */
887 /* step 8.b iv */
888 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
889 result |= Trspi_Hash_DIGEST(&hashCtx, context->transLogDigest.digest);
890 result |= Trspi_Hash_TRANSPORT_LOG_OUT(&hashCtx, &context->transLogOut);
891 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogDigest.digest)))
892 return result;
893 }
894
895 LogDebug("Transport session established successfully");
896
897 pTransAuth = &context->transAuth;
898 pTransAuth->fContinueAuthSession = TRUE;
899 if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
900 (BYTE **)pTransAuth->NonceOdd.nonce))) {
901 LogError("Failed creating random nonce");
902 return TSPERR(TSS_E_INTERNAL_ERROR);
903 }
904
905 return TSS_SUCCESS;
906 }
907
908 TSS_RESULT
do_transport_decryption(TPM_TRANSPORT_PUBLIC * transPub,TPM_AUTH * pTransAuth,BYTE * secret,UINT32 inLen,BYTE * in,UINT32 * outLen,BYTE ** out)909 do_transport_decryption(TPM_TRANSPORT_PUBLIC *transPub,
910 TPM_AUTH *pTransAuth,
911 BYTE *secret,
912 UINT32 inLen,
913 BYTE *in,
914 UINT32 *outLen,
915 BYTE **out)
916 {
917 TSS_RESULT result;
918 UINT32 i, decLen;
919 UINT32 seedLen, ivLen;
920 BYTE *dec;
921 BYTE seed[(2 * sizeof(TPM_NONCE)) + strlen("out") + TPM_SHA1_160_HASH_LEN];
922
923 /* allocate the most data anyone below might need */
924 decLen = inLen;//((inLen / TSS_MAX_SYM_BLOCK_SIZE) + 1) * TSS_MAX_SYM_BLOCK_SIZE;
925 if ((dec = malloc(decLen)) == NULL) {
926 LogError("malloc of %u bytes failed", decLen);
927 return TSPERR(TSS_E_OUTOFMEMORY);
928 }
929
930 /* set the common 3 initial values of 'seed', which is used to generate either the IV or
931 * mask */
932 memcpy(seed, pTransAuth->NonceEven.nonce, sizeof(TPM_NONCE));
933 memcpy(&seed[sizeof(TPM_NONCE)], pTransAuth->NonceOdd.nonce, sizeof(TPM_NONCE));
934 memcpy(&seed[2 * sizeof(TPM_NONCE)], "out", strlen("out"));
935
936 switch (transPub->algId) {
937 case TPM_ALG_MGF1:
938 {
939 decLen = inLen;
940 seedLen = sizeof(seed);
941
942 /* add the secret data to the seed for MGF1 */
943 memcpy(&seed[2 * sizeof(TPM_NONCE) + strlen("out")], secret, TPM_SHA1_160_HASH_LEN);
944
945 if ((result = Trspi_MGF1(TSS_HASH_SHA1, seedLen, seed, decLen, dec))) {
946 free(dec);
947 return result;
948 }
949
950 for (i = 0; i < inLen; i++)
951 dec[i] ^= in[i];
952 break;
953 }
954 case TPM_ALG_AES128:
955 {
956 BYTE iv[TSS_MAX_SYM_BLOCK_SIZE];
957
958 ivLen = TSS_MAX_SYM_BLOCK_SIZE;
959 seedLen = (2 * sizeof(TPM_NONCE)) + strlen("out");
960
961 if ((result = Trspi_MGF1(TSS_HASH_SHA1, seedLen, seed, ivLen, iv))) {
962 free(dec);
963 return result;
964 }
965
966 /* use the secret data as the key for AES */
967 if ((result = Trspi_SymEncrypt(transPub->algId, transPub->encScheme, secret, iv, in,
968 inLen, dec, &decLen))) {
969 free(dec);
970 return result;
971 }
972
973 break;
974 }
975 default:
976 LogDebug("Unknown algorithm for encrypted transport session: 0x%x",
977 transPub->algId);
978 free(dec);
979 return TSPERR(TSS_E_INTERNAL_ERROR);
980 }
981
982 *out = dec;
983 *outLen = decLen;
984
985 return result;
986 }
987
988 TSS_RESULT
do_transport_encryption(TPM_TRANSPORT_PUBLIC * transPub,TPM_AUTH * pTransAuth,BYTE * secret,UINT32 inLen,BYTE * in,UINT32 * outLen,BYTE ** out)989 do_transport_encryption(TPM_TRANSPORT_PUBLIC *transPub,
990 TPM_AUTH *pTransAuth,
991 BYTE *secret,
992 UINT32 inLen,
993 BYTE *in,
994 UINT32 *outLen,
995 BYTE **out)
996 {
997 TSS_RESULT result;
998 UINT32 i, encLen;
999 UINT32 seedLen, ivLen;
1000 BYTE *enc;
1001 BYTE seed[(2 * sizeof(TPM_NONCE)) + strlen("in") + TPM_SHA1_160_HASH_LEN];
1002
1003 /* allocate the most data anyone below might need */
1004 encLen = ((inLen / TSS_MAX_SYM_BLOCK_SIZE) + 1) * TSS_MAX_SYM_BLOCK_SIZE;
1005 if ((enc = malloc(encLen)) == NULL) {
1006 LogError("malloc of %u bytes failed", encLen);
1007 return TSPERR(TSS_E_OUTOFMEMORY);
1008 }
1009
1010 /* set the common 3 initial values of 'seed', which is used to generate either the IV or
1011 * mask */
1012 memcpy(seed, pTransAuth->NonceEven.nonce, sizeof(TPM_NONCE));
1013 memcpy(&seed[sizeof(TPM_NONCE)], pTransAuth->NonceOdd.nonce, sizeof(TPM_NONCE));
1014 memcpy(&seed[2 * sizeof(TPM_NONCE)], "in", strlen("in"));
1015
1016 switch (transPub->algId) {
1017 case TPM_ALG_MGF1:
1018 {
1019 encLen = inLen;
1020 seedLen = sizeof(seed);
1021
1022 /* add the secret data to the seed for MGF1 */
1023 memcpy(&seed[2 * sizeof(TPM_NONCE) + strlen("in")], secret, TPM_SHA1_160_HASH_LEN);
1024
1025 if ((result = Trspi_MGF1(TSS_HASH_SHA1, seedLen, seed, encLen, enc))) {
1026 free(enc);
1027 return result;
1028 }
1029
1030 for (i = 0; i < inLen; i++)
1031 enc[i] ^= in[i];
1032 break;
1033 }
1034 case TPM_ALG_AES128:
1035 {
1036 BYTE iv[TSS_MAX_SYM_BLOCK_SIZE];
1037
1038 ivLen = TSS_MAX_SYM_BLOCK_SIZE;
1039 seedLen = (2 * sizeof(TPM_NONCE)) + strlen("in");
1040
1041 if ((result = Trspi_MGF1(TSS_HASH_SHA1, seedLen, seed, ivLen, iv))) {
1042 free(enc);
1043 return result;
1044 }
1045
1046 /* use the secret data as the key for AES */
1047 if ((result = Trspi_SymEncrypt(transPub->algId, transPub->encScheme, secret, iv, in,
1048 inLen, enc, &encLen))) {
1049 free(enc);
1050 return result;
1051 }
1052
1053 break;
1054 }
1055 default:
1056 LogDebug("Unknown algorithm for encrypted transport session: 0x%x",
1057 transPub->algId);
1058 free(enc);
1059 return TSPERR(TSS_E_INTERNAL_ERROR);
1060 }
1061
1062 *out = enc;
1063 *outLen = encLen;
1064
1065 return result;
1066 }
1067
1068 TSS_RESULT
obj_context_transport_execute(TSS_HCONTEXT tspContext,TPM_COMMAND_CODE ordinal,UINT32 ulDataLen,BYTE * rgbData,TPM_DIGEST * pubKeyHash,UINT32 * handlesLen,TCS_HANDLE ** handles,TPM_AUTH * pAuth1,TPM_AUTH * pAuth2,UINT32 * outLen,BYTE ** out)1069 obj_context_transport_execute(TSS_HCONTEXT tspContext,
1070 TPM_COMMAND_CODE ordinal,
1071 UINT32 ulDataLen,
1072 BYTE* rgbData,
1073 TPM_DIGEST* pubKeyHash,
1074 UINT32* handlesLen,
1075 TCS_HANDLE** handles,
1076 TPM_AUTH* pAuth1,
1077 TPM_AUTH* pAuth2,
1078 UINT32* outLen,
1079 BYTE** out)
1080 {
1081 TSS_RESULT result = TSS_SUCCESS;
1082 struct tsp_object *obj;
1083 struct tr_context_obj *context;
1084 UINT32 encLen, ulWrappedDataLen = 0;
1085 BYTE *pEnc = NULL, *rgbWrappedData = NULL;
1086 TPM_RESULT tpmResult;
1087 Trspi_HashCtx hashCtx;
1088 TPM_DIGEST etDigest, wDigest;
1089 TPM_AUTH *pTransAuth;
1090 UINT64 currentTicks;
1091 TSS_BOOL free_enc = FALSE;
1092
1093 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
1094 return TSPERR(TSS_E_INVALID_HANDLE);
1095
1096 context = (struct tr_context_obj *)obj->data;
1097
1098 pTransAuth = &context->transAuth;
1099
1100 /* TPM Commands spec rev106 step 6 */
1101 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1102 result |= Trspi_Hash_UINT32(&hashCtx, ordinal);
1103
1104 switch (ordinal) {
1105 case TPM_ORD_OSAP:
1106 case TPM_ORD_OIAP:
1107 break;
1108 default:
1109 result |= Trspi_HashUpdate(&hashCtx, ulDataLen, rgbData);
1110 break;
1111 }
1112
1113 if ((result |= Trspi_HashFinal(&hashCtx, wDigest.digest)))
1114 goto done;
1115
1116 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) {
1117 /* TPM Commands spec rev106 step 10.b */
1118 memcpy(context->transLogIn.parameters.digest, wDigest.digest, sizeof(TPM_DIGEST));
1119 /* TPM Commands spec rev106 step 10.c, d or e, calculated by the caller */
1120 if (pubKeyHash)
1121 memcpy(context->transLogIn.pubKeyHash.digest, pubKeyHash->digest,
1122 sizeof(TPM_DIGEST));
1123 else
1124 __tspi_memset(context->transLogIn.pubKeyHash.digest, 0, sizeof(TPM_DIGEST));
1125
1126 /* TPM Commands spec rev106 step 10.f */
1127 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1128 result |= Trspi_Hash_DIGEST(&hashCtx, context->transLogDigest.digest);
1129 result |= Trspi_Hash_TRANSPORT_LOG_IN(&hashCtx, &context->transLogIn);
1130 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogDigest.digest)))
1131 goto done;
1132 }
1133
1134 /* TPM Commands spec rev106 step 7.a */
1135 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1136 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ExecuteTransport);
1137 result |= Trspi_Hash_UINT32(&hashCtx, ulDataLen + TSS_TPM_TXBLOB_HDR_LEN
1138 + (*handlesLen * sizeof(UINT32))
1139 + (pAuth1 ? TPM_AUTH_RQU_SIZE : 0)
1140 + (pAuth2 ? TPM_AUTH_RQU_SIZE : 0));
1141 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, wDigest.digest);
1142 if ((result |= Trspi_HashFinal(&hashCtx, etDigest.digest)))
1143 goto done;
1144
1145 /* encrypt the data if necessary */
1146 if (ulDataLen && context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT) {
1147 switch (ordinal) {
1148 case TPM_ORD_OSAP:
1149 case TPM_ORD_OIAP:
1150 encLen = ulDataLen;
1151 pEnc = rgbData;
1152 break;
1153 case TPM_ORD_DSAP:
1154 {
1155 UINT64 offset;
1156 UINT32 tmpLen, entityValueLen;
1157 BYTE *tmpEnc, *entityValuePtr;
1158
1159 /* DSAP is a special case where only entityValue is encrypted. So, we'll
1160 * parse through rgbData until we get to entityValue, encrypt it, alloc
1161 * new space for rgbData (since it could be up to a block length larger
1162 * than it came in) and copy the unencrypted data and the encrypted
1163 * entityValue to the new block, setting pEnc and encLen to new values. */
1164
1165 offset = (2 * sizeof(UINT32)) + sizeof(TPM_NONCE);
1166 Trspi_UnloadBlob_UINT32(&offset, &entityValueLen, rgbData);
1167
1168 entityValuePtr = &rgbData[offset];
1169 if ((result = do_transport_encryption(&context->transPub, pTransAuth,
1170 context->transSecret.authData.authdata,
1171 entityValueLen, entityValuePtr, &tmpLen,
1172 &tmpEnc)))
1173 goto done;
1174
1175 /* offset is the amount of data before the block we encrypted and tmpLen is
1176 * the size of the encrypted data */
1177 encLen = offset + tmpLen;
1178 if ((pEnc = malloc(encLen)) == NULL) {
1179 LogError("malloc of %u bytes failed.", encLen);
1180 result = TSPERR(TSS_E_OUTOFMEMORY);
1181 goto done;
1182 }
1183 memcpy(pEnc, rgbData, offset);
1184 memcpy(&pEnc[offset], tmpEnc, tmpLen);
1185 free(tmpEnc);
1186
1187 free_enc = TRUE;
1188 break;
1189 }
1190 default:
1191 if ((result = do_transport_encryption(&context->transPub, pTransAuth,
1192 context->transSecret.authData.authdata,
1193 ulDataLen, rgbData, &encLen, &pEnc)))
1194 goto done;
1195
1196 free_enc = TRUE;
1197 break;
1198 }
1199 } else {
1200 encLen = ulDataLen;
1201 pEnc = rgbData;
1202 }
1203
1204 /* TPM Commands spec rev106 step 7.b */
1205 HMAC_Auth(context->transSecret.authData.authdata, etDigest.digest, pTransAuth);
1206
1207 if ((result = RPC_ExecuteTransport(tspContext, ordinal, encLen, pEnc, handlesLen, handles,
1208 pAuth1, pAuth2, pTransAuth, ¤tTicks,
1209 &context->transMod, &tpmResult, &ulWrappedDataLen,
1210 &rgbWrappedData))) {
1211 LogDebugFn("Execute Transport failed: %s", Trspi_Error_String(result));
1212 goto done;
1213 }
1214
1215 if (tpmResult) {
1216 LogDebug("Wrapped command ordinal 0x%x failed with result: 0x%x", ordinal,
1217 tpmResult);
1218 result = tpmResult;
1219 goto done;
1220 }
1221
1222 /* decrypt the returned wrapped data if necessary */
1223 if (ulWrappedDataLen && context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_DEFAULT_ENCRYPT) {
1224 switch (ordinal) {
1225 case TPM_ORD_OSAP:
1226 case TPM_ORD_OIAP:
1227 case TPM_ORD_DSAP:
1228 *outLen = ulWrappedDataLen;
1229 *out = rgbWrappedData;
1230 break;
1231 default:
1232 if ((result = do_transport_decryption(&context->transPub, pTransAuth,
1233 context->transSecret.authData.authdata,
1234 ulWrappedDataLen, rgbWrappedData, outLen,
1235 out)))
1236 goto done;
1237
1238 free(rgbWrappedData);
1239 }
1240 } else {
1241 if (outLen) {
1242 *outLen = ulWrappedDataLen;
1243 *out = rgbWrappedData;
1244 }
1245 }
1246
1247 /* TPM Commands spec rev106 step 14 */
1248 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1249 result |= Trspi_Hash_UINT32(&hashCtx, tpmResult);
1250 result |= Trspi_Hash_UINT32(&hashCtx, ordinal);
1251
1252 switch (ordinal) {
1253 case TPM_ORD_OSAP:
1254 case TPM_ORD_OIAP:
1255 break;
1256 default:
1257 if (outLen)
1258 result |= Trspi_HashUpdate(&hashCtx, *outLen, *out);
1259 break;
1260 }
1261
1262 if ((result |= Trspi_HashFinal(&hashCtx, wDigest.digest)))
1263 goto done;
1264
1265 /* TPM Commands spec rev106 step 15 */
1266 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1267 result |= Trspi_Hash_UINT32(&hashCtx, result);
1268 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ExecuteTransport);
1269 result |= Trspi_Hash_UINT64(&hashCtx, currentTicks);
1270 result |= Trspi_Hash_UINT32(&hashCtx, context->transMod);
1271 result |= Trspi_Hash_UINT32(&hashCtx, (outLen ? *outLen : 0)
1272 + TSS_TPM_TXBLOB_HDR_LEN
1273 + (*handlesLen * sizeof(UINT32))
1274 + (pAuth1 ? TPM_AUTH_RSP_SIZE : 0)
1275 + (pAuth2 ? TPM_AUTH_RSP_SIZE : 0));
1276 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, wDigest.digest);
1277 if ((result |= Trspi_HashFinal(&hashCtx, etDigest.digest)))
1278 goto done;
1279
1280 if (validateReturnAuth(context->transSecret.authData.authdata, etDigest.digest,
1281 pTransAuth)) {
1282 result = TSPERR(TSS_E_TSP_TRANS_AUTHFAIL);
1283 goto done;
1284 }
1285
1286 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) {
1287 context->transLogOut.currentTicks.currentTicks = currentTicks;
1288
1289 /* TPM Commands spec rev106 step 16.b */
1290 memcpy(context->transLogOut.parameters.digest, wDigest.digest, sizeof(TPM_DIGEST));
1291 /* TPM Commands spec rev106 step 16.c done above */
1292 /* TPM Commands spec rev106 step 16.d */
1293 context->transLogOut.locality = context->transMod;
1294
1295 /* TPM Commands spec rev106 step 16.d */
1296 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1297 result |= Trspi_Hash_DIGEST(&hashCtx, context->transLogDigest.digest);
1298 result |= Trspi_Hash_TRANSPORT_LOG_OUT(&hashCtx, &context->transLogOut);
1299 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogDigest.digest)))
1300 goto done;
1301 }
1302
1303 /* Refresh nonceOdd for continued transport auth session */
1304 if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
1305 (BYTE **)pTransAuth->NonceOdd.nonce))) {
1306 LogError("Failed creating random nonce");
1307 }
1308
1309 done:
1310 if (free_enc)
1311 free(pEnc);
1312 obj_list_put(&context_list);
1313
1314 return result;
1315 }
1316
1317 /* called to close a transport session */
1318 TSS_RESULT
obj_context_transport_close(TSS_HCONTEXT tspContext,TSS_HKEY hKey,TSS_HPOLICY hPolicy,TSS_BOOL usesAuth,TPM_SIGN_INFO * signInfo,UINT32 * sigLen,BYTE ** sig)1319 obj_context_transport_close(TSS_HCONTEXT tspContext,
1320 TSS_HKEY hKey,
1321 TSS_HPOLICY hPolicy,
1322 TSS_BOOL usesAuth,
1323 TPM_SIGN_INFO* signInfo,
1324 UINT32* sigLen,
1325 BYTE** sig)
1326 {
1327 TSS_RESULT result = TSS_SUCCESS;
1328 struct tsp_object *obj;
1329 struct tr_context_obj *context;
1330 Trspi_HashCtx hashCtx;
1331 TPM_DIGEST digest;
1332 TPM_AUTH auth, *pAuth;
1333 TCS_KEY_HANDLE tcsKey;
1334 BYTE *ticks = NULL;
1335 UINT32 tickLen;
1336
1337 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
1338 return TSPERR(TSS_E_INVALID_HANDLE);
1339
1340 context = (struct tr_context_obj *)obj->data;
1341
1342 /* return immediately if we're not in a transport session */
1343 if (!(context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_ENABLED)) {
1344 result = TSPERR(TSS_E_INTERNAL_ERROR);
1345 goto done;
1346 }
1347
1348 if ((result = obj_rsakey_get_tcs_handle(hKey, &tcsKey)))
1349 goto done;
1350
1351 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1352 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ReleaseTransportSigned);
1353 result |= Trspi_Hash_NONCE(&hashCtx, signInfo->replay.nonce);
1354 if ((result |= Trspi_HashFinal(&hashCtx, (BYTE *)&digest)))
1355 goto done;
1356
1357 if (usesAuth) {
1358 if ((result = secret_PerformAuth_OIAP(hKey, TPM_ORD_ReleaseTransportSigned,
1359 hPolicy, FALSE, &digest, &auth)))
1360 goto done;
1361
1362 pAuth = &auth;
1363 } else
1364 pAuth = NULL;
1365
1366 /* continue the auth session established in obj_context_transport_establish */
1367 HMAC_Auth(context->transSecret.authData.authdata, digest.digest, &context->transAuth);
1368
1369 if ((result = RPC_ReleaseTransportSigned(tspContext, tcsKey, &signInfo->replay, pAuth,
1370 &context->transAuth,
1371 &context->transLogOut.locality, &tickLen, &ticks,
1372 sigLen, sig)))
1373 goto done;
1374
1375 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1376 result |= Trspi_Hash_UINT32(&hashCtx, result);
1377 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ReleaseTransportSigned);
1378 result |= Trspi_Hash_UINT32(&hashCtx, context->transLogOut.locality);
1379 result |= Trspi_HashUpdate(&hashCtx, tickLen, ticks);
1380 result |= Trspi_Hash_UINT32(&hashCtx, *sigLen);
1381 result |= Trspi_HashUpdate(&hashCtx, *sigLen, *sig);
1382 if ((result |= Trspi_HashFinal(&hashCtx, (BYTE *)&digest)))
1383 goto done_disabled;
1384
1385 /* validate the return data using the key's auth */
1386 if (pAuth) {
1387 if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, pAuth)))
1388 goto done_disabled;
1389 }
1390
1391 /* validate again using the transport session's auth */
1392 if ((result = validateReturnAuth(context->transSecret.authData.authdata, digest.digest,
1393 &context->transAuth))) {
1394 result = TSPERR(TSS_E_TSP_TRANS_AUTHFAIL);
1395 goto done_disabled;
1396 }
1397
1398 if (context->flags & TSS_CONTEXT_FLAGS_TRANSPORT_AUTHENTIC) {
1399 UINT64 offset;
1400
1401 /* TPM Commands Spec step 6.b */
1402 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1403 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ReleaseTransportSigned);
1404 result |= Trspi_Hash_NONCE(&hashCtx, signInfo->replay.nonce);
1405 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogOut.parameters.digest)))
1406 goto done_disabled;
1407
1408 /* TPM Commands Spec step 6.c */
1409 offset = 0;
1410 Trspi_UnloadBlob_CURRENT_TICKS(&offset, ticks, &context->transLogOut.currentTicks);
1411 free(ticks);
1412
1413 /* TPM Commands Spec step 6.d was set above */
1414 /* TPM Commands Spec step 6.e */
1415 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1416 result |= Trspi_Hash_DIGEST(&hashCtx, context->transLogDigest.digest);
1417 result |= Trspi_Hash_TRANSPORT_LOG_OUT(&hashCtx, &context->transLogOut);
1418 if ((result |= Trspi_HashFinal(&hashCtx, context->transLogDigest.digest)))
1419 goto done_disabled;
1420 }
1421
1422 if ((signInfo->data = malloc(sizeof(TPM_DIGEST))) == NULL) {
1423 LogError("malloc %zd bytes failed.", sizeof(TPM_DIGEST));
1424 result = TSPERR(TSS_E_OUTOFMEMORY);
1425 goto done_disabled;
1426 }
1427 memcpy(signInfo->data, context->transLogDigest.digest, sizeof(TPM_DIGEST));
1428 signInfo->dataLen = sizeof(TPM_DIGEST);
1429
1430 /* destroy all transport session info, except the key handle */
1431 __tspi_memset(&context->transPub, 0, sizeof(TPM_TRANSPORT_PUBLIC));
1432 __tspi_memset(&context->transMod, 0, sizeof(TPM_MODIFIER_INDICATOR));
1433 __tspi_memset(&context->transSecret, 0, sizeof(TPM_TRANSPORT_AUTH));
1434 __tspi_memset(&context->transAuth, 0, sizeof(TPM_AUTH));
1435 __tspi_memset(&context->transLogIn, 0, sizeof(TPM_TRANSPORT_LOG_IN));
1436 __tspi_memset(&context->transLogOut, 0, sizeof(TPM_TRANSPORT_LOG_OUT));
1437 __tspi_memset(&context->transLogDigest, 0, sizeof(TPM_DIGEST));
1438
1439 done_disabled:
1440 context->flags &= ~TSS_CONTEXT_FLAGS_TRANSPORT_ESTABLISHED;
1441 done:
1442 obj_list_put(&context_list);
1443
1444 return result;
1445 }
1446 #endif
1447
1448 /* XXX change 0,1,2 to #defines */
1449 TSS_RESULT
obj_context_set_tpm_version(TSS_HCONTEXT tspContext,UINT32 ver)1450 obj_context_set_tpm_version(TSS_HCONTEXT tspContext, UINT32 ver)
1451 {
1452 TSS_RESULT result = TSS_SUCCESS;
1453 struct tsp_object *obj;
1454 struct tr_context_obj *context;
1455
1456 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
1457 return TSPERR(TSS_E_INVALID_HANDLE);
1458
1459 context = (struct tr_context_obj *)obj->data;
1460
1461 switch (ver) {
1462 case 1:
1463 context->flags &= ~TSS_CONTEXT_FLAGS_TPM_VERSION_MASK;
1464 context->flags |= TSS_CONTEXT_FLAGS_TPM_VERSION_1;
1465 break;
1466 case 2:
1467 context->flags &= ~TSS_CONTEXT_FLAGS_TPM_VERSION_MASK;
1468 context->flags |= TSS_CONTEXT_FLAGS_TPM_VERSION_2;
1469 break;
1470 default:
1471 LogError("Invalid TPM version set: %u", ver);
1472 result = TSPERR(TSS_E_INTERNAL_ERROR);
1473 break;
1474 }
1475
1476 obj_list_put(&context_list);
1477
1478 return result;
1479 }
1480
1481 /* XXX change 0,1,2 to #defines */
1482 TSS_RESULT
obj_context_get_tpm_version(TSS_HCONTEXT tspContext,UINT32 * ver)1483 obj_context_get_tpm_version(TSS_HCONTEXT tspContext, UINT32 *ver)
1484 {
1485 struct tsp_object *obj;
1486 struct tr_context_obj *context;
1487
1488 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
1489 return TSPERR(TSS_E_INVALID_HANDLE);
1490
1491 context = (struct tr_context_obj *)obj->data;
1492
1493 if (context->flags & TSS_CONTEXT_FLAGS_TPM_VERSION_1)
1494 *ver = 1;
1495 else if (context->flags & TSS_CONTEXT_FLAGS_TPM_VERSION_2)
1496 *ver = 2;
1497 else
1498 *ver = 0;
1499
1500 obj_list_put(&context_list);
1501
1502 return TSS_SUCCESS;
1503 }
1504
1505 TSS_RESULT
obj_context_get_loadkey_ordinal(TSS_HCONTEXT tspContext,TPM_COMMAND_CODE * ordinal)1506 obj_context_get_loadkey_ordinal(TSS_HCONTEXT tspContext, TPM_COMMAND_CODE *ordinal)
1507 {
1508 struct tsp_object *obj;
1509 struct tr_context_obj *context;
1510
1511 if ((obj = obj_list_get_obj(&context_list, tspContext)) == NULL)
1512 return TSPERR(TSS_E_INVALID_HANDLE);
1513
1514 context = (struct tr_context_obj *)obj->data;
1515
1516 switch (context->flags & TSS_CONTEXT_FLAGS_TPM_VERSION_MASK) {
1517 case TSS_CONTEXT_FLAGS_TPM_VERSION_2:
1518 *ordinal = TPM_ORD_LoadKey2;
1519 break;
1520 default:
1521 LogDebugFn("No TPM version set!");
1522 /* fall through */
1523 case TSS_CONTEXT_FLAGS_TPM_VERSION_1:
1524 *ordinal = TPM_ORD_LoadKey;
1525 break;
1526 }
1527
1528 obj_list_put(&context_list);
1529
1530 return TSS_SUCCESS;
1531 }
1532
1533