~ubuntu-branches/ubuntu/hardy/trousers/hardy-proposed

« back to all changes in this revision

Viewing changes to src/tspi/obj_context.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2008-01-23 22:03:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080123220300-fhtqja3c0oq0gp6z
Tags: 0.3.1-4
* Added patch from Aaron M. Ucko <ucko@debian.org> to allow trousers to
  build successfully on amd64, and presumably also other 64-bit
  architectures (Closes: #457400).
* Including udev rule for /dev/tpm from William Lima
  <wlima.amadeus@gmail.com> as suggested by David Smith <dds@google.com>
  (Closes: #459682).
* Added lintian overrides.

Show diffs side-by-side

added added

removed removed

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