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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 3: Commands
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014
#include "InternalRoutines.h"
#include "Import_fp.h"
#include "Object_spt_fp.h"
//
//
// Error Returns Meaning
//
// TPM_RC_ASYMMETRIC non-duplicable storage key represented by objectPublic and its
// parent referenced by parentHandle have different public parameters
// TPM_RC_ATTRIBUTES attributes FixedTPM and fixedParent of objectPublic are not both
// CLEAR; or inSymSeed is nonempty and parentHandle does not
// reference a decryption key; or objectPublic and parentHandle have
// incompatible or inconsistent attributes; or encrytpedDuplication is
// SET in objectPublic but the inner or outer wrapper is missing.
//
// NOTE: if the TPM provides parameter values, the parameter number will indicate symmetricKey (missing
// inner wrapper) or inSymSeed (missing outer wrapper).
//
//
// TPM_RC_BINDING duplicate and objectPublic are not cryptographically
// bound
//
// TPM_RC_ECC_POINT inSymSeed is nonempty and ECC point in inSymSeed is not on the
// curve
// TPM_RC_HASH non-duplicable storage key represented by objectPublic and its
// parent referenced by parentHandle have different name algorithm
// TPM_RC_INSUFFICIENT inSymSeed is nonempty and failed to retrieve ECC point from the
// secret; or unmarshaling sensitive value from duplicate failed the
// result of inSymSeed decryption
// TPM_RC_INTEGRITY duplicate integrity is broken
// TPM_RC_KDF objectPublic representing decrypting keyed hash object specifies
// invalid KDF
// TPM_RC_KEY inconsistent parameters of objectPublic; or inSymSeed is nonempty
// and parentHandle does not reference a key of supported type; or
// invalid key size in objectPublic representing an asymmetric key
// TPM_RC_NO_RESULT inSymSeed is nonempty and multiplication resulted in ECC point at
// infinity
// TPM_RC_OBJECT_MEMORY no available object slot
// TPM_RC_SCHEME inconsistent attributes decrypt, sign, restricted and key's scheme ID
// in objectPublic; or hash algorithm is inconsistent with the scheme ID
// for keyed hash object
// TPM_RC_SIZE authPolicy size does not match digest size of the name algorithm in
// objectPublic; or symmetricAlg and encryptionKey have different
// sizes; or inSymSeed is nonempty and it size is not consistent with the
// type of parentHandle; or unmarshaling sensitive value from duplicate
// failed
// TPM_RC_SYMMETRIC objectPublic is either a storage key with no symmetric algorithm or a
// non-storage key with symmetric algorithm different from
// TPM_ALG_NULL
// TPM_RC_TYPE unsupported type of objectPublic; or non-duplicable storage key
// represented by objectPublic and its parent referenced by
// parentHandle are of different types; or parentHandle is not a storage
// key; or only the public portion of parentHandle is loaded; or
// objectPublic and duplicate are of different types
// TPM_RC_VALUE nonempty inSymSeed and its numeric value is greater than the
// modulus of the key referenced by parentHandle or inSymSeed is
// larger than the size of the digest produced by the name algorithm of
// the symmetric key referenced by parentHandle
//
TPM_RC
TPM2_Import(
Import_In *in, // IN: input parameter list
Import_Out *out // OUT: output parameter list
)
{
TPM_RC result = TPM_RC_SUCCESS;
OBJECT *parentObject;
TPM2B_DATA data; // symmetric key
TPMT_SENSITIVE sensitive;
TPM2B_NAME name;
UINT16 innerKeySize = 0; // encrypt key size for inner
// wrapper
// Input Validation
// FixedTPM and fixedParent must be CLEAR
if( in->objectPublic.t.publicArea.objectAttributes.fixedTPM == SET
|| in->objectPublic.t.publicArea.objectAttributes.fixedParent == SET)
return TPM_RC_ATTRIBUTES + RC_Import_objectPublic;
// Get parent pointer
parentObject = ObjectGet(in->parentHandle);
if(!AreAttributesForParent(parentObject))
return TPM_RC_TYPE + RC_Import_parentHandle;
if(in->symmetricAlg.algorithm != TPM_ALG_NULL)
{
// Get inner wrap key size
innerKeySize = in->symmetricAlg.keyBits.sym;
// Input symmetric key must match the size of algorithm.
if(in->encryptionKey.t.size != (innerKeySize + 7) / 8)
return TPM_RC_SIZE + RC_Import_encryptionKey;
}
else
{
// If input symmetric algorithm is NULL, input symmetric key size must
// be 0 as well
if(in->encryptionKey.t.size != 0)
return TPM_RCS_SIZE + RC_Import_encryptionKey;
// If encryptedDuplication is SET, then the object must have an inner
// wrapper
if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication)
return TPM_RCS_ATTRIBUTES + RC_Import_encryptionKey;
}
// See if there is an outer wrapper
if(in->inSymSeed.t.size != 0)
{
// Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES,
// TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT,
// TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point
result = CryptSecretDecrypt(in->parentHandle, NULL, "DUPLICATE",
&in->inSymSeed, &data);
pAssert(result != TPM_RC_BINDING);
//
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result, RC_Import_inSymSeed);
}
else
{
// If encrytpedDuplication is set, then the object must have an outer
// wrapper
if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication)
return TPM_RCS_ATTRIBUTES + RC_Import_inSymSeed;
data.t.size = 0;
}
// Compute name of object
ObjectComputeName(&(in->objectPublic.t.publicArea), &name);
// Retrieve sensitive from private.
// TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here.
result = DuplicateToSensitive(&in->duplicate, &name, in->parentHandle,
in->objectPublic.t.publicArea.nameAlg,
(TPM2B_SEED *) &data, &in->symmetricAlg,
&in->encryptionKey, &sensitive);
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result, RC_Import_duplicate);
// If the parent of this object has fixedTPM SET, then fully validate this
// object so that validation can be skipped when it is loaded
if(parentObject->publicArea.objectAttributes.fixedTPM == SET)
{
TPM_HANDLE objectHandle;
// Perform self check on input public area. A TPM_RC_SIZE, TPM_RC_SCHEME,
// TPM_RC_VALUE, TPM_RC_SYMMETRIC, TPM_RC_TYPE, TPM_RC_HASH,
// TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES or TPM_RC_KDF error may be returned
// at this point
result = PublicAttributesValidation(TRUE, in->parentHandle,
&in->objectPublic.t.publicArea);
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result, RC_Import_objectPublic);
// Create internal object. A TPM_RC_KEY_SIZE, TPM_RC_KEY or
// TPM_RC_OBJECT_MEMORY error may be returned at this point
result = ObjectLoad(TPM_RH_NULL, &in->objectPublic.t.publicArea,
&sensitive, NULL, in->parentHandle, FALSE,
&objectHandle);
if(result != TPM_RC_SUCCESS)
return result;
// Don't need the object, just needed the checks to be performed so
// flush the object
ObjectFlush(objectHandle);
}
// Command output
// Prepare output private data from sensitive
SensitiveToPrivate(&sensitive, &name, in->parentHandle,
in->objectPublic.t.publicArea.nameAlg,
&out->outPrivate);
return TPM_RC_SUCCESS;
}
|