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