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, &currentTicks,
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