1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 4: Supporting Routines
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014
#include "InternalRoutines.h"
#include "Context_spt_fp.h"
//
//
// Functions
//
// ComputeContextProtectionKey()
//
// This function retrieves the symmetric protection key for context encryption It is used by
// TPM2_ConextSave() and TPM2_ContextLoad() to create the symmetric encryption key and iv
//
void
ComputeContextProtectionKey(
TPMS_CONTEXT *contextBlob, // IN: context blob
TPM2B_SYM_KEY *symKey, // OUT: the symmetric key
TPM2B_IV *iv // OUT: the IV.
)
{
UINT16 symKeyBits; // number of bits in the parent's
// symmetric key
TPM2B_AUTH *proof = NULL; // the proof value to use. Is null for
// everything but a primary object in
// the Endorsement Hierarchy
BYTE kdfResult[sizeof(TPMU_HA) * 2];// Value produced by the KDF
TPM2B_DATA sequence2B, handle2B;
// Get proof value
proof = HierarchyGetProof(contextBlob->hierarchy);
// Get sequence value in 2B format
sequence2B.t.size = sizeof(contextBlob->sequence);
MemoryCopy(sequence2B.t.buffer, &contextBlob->sequence,
sizeof(contextBlob->sequence),
sizeof(sequence2B.t.buffer));
// Get handle value in 2B format
handle2B.t.size = sizeof(contextBlob->savedHandle);
MemoryCopy(handle2B.t.buffer, &contextBlob->savedHandle,
sizeof(contextBlob->savedHandle),
sizeof(handle2B.t.buffer));
// Get the symmetric encryption key size
symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES;
//
symKeyBits = CONTEXT_ENCRYPT_KEY_BITS;
// Get the size of the IV for the algorithm
iv->t.size = CryptGetSymmetricBlockSize(CONTEXT_ENCRYPT_ALG, symKeyBits);
// KDFa to generate symmetric key and IV value
KDFa(CONTEXT_INTEGRITY_HASH_ALG, &proof->b, "CONTEXT", &sequence2B.b,
&handle2B.b, (symKey->t.size + iv->t.size) * 8, kdfResult, NULL);
// Copy part of the returned value as the key
MemoryCopy(symKey->t.buffer, kdfResult, symKey->t.size,
sizeof(symKey->t.buffer));
// Copy the rest as the IV
MemoryCopy(iv->t.buffer, &kdfResult[symKey->t.size], iv->t.size,
sizeof(iv->t.buffer));
return;
}
//
//
// ComputeContextIntegrity()
//
// Generate the integrity hash for a context It is used by TPM2_ContextSave() to create an integrity hash
// and by TPM2_ContextLoad() to compare an integrity hash
//
void
ComputeContextIntegrity(
TPMS_CONTEXT *contextBlob, // IN: context blob
TPM2B_DIGEST *integrity // OUT: integrity
)
{
HMAC_STATE hmacState;
TPM2B_AUTH *proof;
UINT16 integritySize;
// Get proof value
proof = HierarchyGetProof(contextBlob->hierarchy);
// Start HMAC
integrity->t.size = CryptStartHMAC2B(CONTEXT_INTEGRITY_HASH_ALG,
&proof->b, &hmacState);
// Compute integrity size at the beginning of context blob
integritySize = sizeof(integrity->t.size) + integrity->t.size;
// Adding total reset counter so that the context cannot be
// used after a TPM Reset
CryptUpdateDigestInt(&hmacState, sizeof(gp.totalResetCount),
&gp.totalResetCount);
// If this is a ST_CLEAR object, add the clear count
// so that this contest cannot be loaded after a TPM Restart
if(contextBlob->savedHandle == 0x80000002)
CryptUpdateDigestInt(&hmacState, sizeof(gr.clearCount), &gr.clearCount);
// Adding sequence number to the HMAC to make sure that it doesn't
// get changed
CryptUpdateDigestInt(&hmacState, sizeof(contextBlob->sequence),
&contextBlob->sequence);
// Protect the handle
CryptUpdateDigestInt(&hmacState, sizeof(contextBlob->savedHandle),
&contextBlob->savedHandle);
// Adding sensitive contextData, skip the leading integrity area
CryptUpdateDigest(&hmacState, contextBlob->contextBlob.t.size - integritySize,
contextBlob->contextBlob.t.buffer + integritySize);
// Complete HMAC
CryptCompleteHMAC2B(&hmacState, &integrity->b);
return;
}
//
//
// SequenceDataImportExport()
//
// This function is used scan through the sequence object and either modify the hash state data for
// LIB_EXPORT or to import it into the internal format
//
void
SequenceDataImportExport(
OBJECT *object, // IN: the object containing the sequence data
OBJECT *exportObject, // IN/OUT: the object structure that will get
// the exported hash state
IMPORT_EXPORT direction
)
{
int count = 1;
HASH_OBJECT *internalFmt = (HASH_OBJECT *)object;
HASH_OBJECT *externalFmt = (HASH_OBJECT *)exportObject;
if(object->attributes.eventSeq)
count = HASH_COUNT;
for(; count; count--)
CryptHashStateImportExport(&internalFmt->state.hashState[count - 1],
externalFmt->state.hashState, direction);
}
|