blob: fef4b664759e2381d6c5ac6f0d0816be6017d463 [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// This file was extracted from the TCG Published
2// Trusted Platform Module Library
3// Part 3: Commands
4// Family "2.0"
5// Level 00 Revision 01.16
6// October 30, 2014
7
8#include "InternalRoutines.h"
9#include "Import_fp.h"
10#include "Object_spt_fp.h"
11//
12//
13// Error Returns Meaning
14//
15// TPM_RC_ASYMMETRIC non-duplicable storage key represented by objectPublic and its
16// parent referenced by parentHandle have different public parameters
17// TPM_RC_ATTRIBUTES attributes FixedTPM and fixedParent of objectPublic are not both
18// CLEAR; or inSymSeed is nonempty and parentHandle does not
19// reference a decryption key; or objectPublic and parentHandle have
20// incompatible or inconsistent attributes; or encrytpedDuplication is
21// SET in objectPublic but the inner or outer wrapper is missing.
22//
23// NOTE: if the TPM provides parameter values, the parameter number will indicate symmetricKey (missing
24// inner wrapper) or inSymSeed (missing outer wrapper).
25//
26//
27// TPM_RC_BINDING duplicate and objectPublic are not cryptographically
28// bound
29//
30// TPM_RC_ECC_POINT inSymSeed is nonempty and ECC point in inSymSeed is not on the
31// curve
32// TPM_RC_HASH non-duplicable storage key represented by objectPublic and its
33// parent referenced by parentHandle have different name algorithm
34// TPM_RC_INSUFFICIENT inSymSeed is nonempty and failed to retrieve ECC point from the
35// secret; or unmarshaling sensitive value from duplicate failed the
36// result of inSymSeed decryption
37// TPM_RC_INTEGRITY duplicate integrity is broken
38// TPM_RC_KDF objectPublic representing decrypting keyed hash object specifies
39// invalid KDF
40// TPM_RC_KEY inconsistent parameters of objectPublic; or inSymSeed is nonempty
41// and parentHandle does not reference a key of supported type; or
42// invalid key size in objectPublic representing an asymmetric key
43// TPM_RC_NO_RESULT inSymSeed is nonempty and multiplication resulted in ECC point at
44// infinity
45// TPM_RC_OBJECT_MEMORY no available object slot
46// TPM_RC_SCHEME inconsistent attributes decrypt, sign, restricted and key's scheme ID
47// in objectPublic; or hash algorithm is inconsistent with the scheme ID
48// for keyed hash object
49// TPM_RC_SIZE authPolicy size does not match digest size of the name algorithm in
50// objectPublic; or symmetricAlg and encryptionKey have different
51// sizes; or inSymSeed is nonempty and it size is not consistent with the
52// type of parentHandle; or unmarshaling sensitive value from duplicate
53// failed
54// TPM_RC_SYMMETRIC objectPublic is either a storage key with no symmetric algorithm or a
55// non-storage key with symmetric algorithm different from
56// TPM_ALG_NULL
57// TPM_RC_TYPE unsupported type of objectPublic; or non-duplicable storage key
58// represented by objectPublic and its parent referenced by
59// parentHandle are of different types; or parentHandle is not a storage
60// key; or only the public portion of parentHandle is loaded; or
61// objectPublic and duplicate are of different types
62// TPM_RC_VALUE nonempty inSymSeed and its numeric value is greater than the
63// modulus of the key referenced by parentHandle or inSymSeed is
64// larger than the size of the digest produced by the name algorithm of
65// the symmetric key referenced by parentHandle
66//
67TPM_RC
68TPM2_Import(
69 Import_In *in, // IN: input parameter list
70 Import_Out *out // OUT: output parameter list
71 )
72{
73
74 TPM_RC result = TPM_RC_SUCCESS;
75 OBJECT *parentObject;
76 TPM2B_DATA data; // symmetric key
77 TPMT_SENSITIVE sensitive;
78 TPM2B_NAME name;
79
80 UINT16 innerKeySize = 0; // encrypt key size for inner
81 // wrapper
82
83// Input Validation
84
85 // FixedTPM and fixedParent must be CLEAR
86 if( in->objectPublic.t.publicArea.objectAttributes.fixedTPM == SET
87 || in->objectPublic.t.publicArea.objectAttributes.fixedParent == SET)
88 return TPM_RC_ATTRIBUTES + RC_Import_objectPublic;
89
90 // Get parent pointer
91 parentObject = ObjectGet(in->parentHandle);
92
93 if(!AreAttributesForParent(parentObject))
94 return TPM_RC_TYPE + RC_Import_parentHandle;
95
96 if(in->symmetricAlg.algorithm != TPM_ALG_NULL)
97 {
98 // Get inner wrap key size
99 innerKeySize = in->symmetricAlg.keyBits.sym;
100 // Input symmetric key must match the size of algorithm.
101 if(in->encryptionKey.t.size != (innerKeySize + 7) / 8)
102 return TPM_RC_SIZE + RC_Import_encryptionKey;
103 }
104 else
105 {
106 // If input symmetric algorithm is NULL, input symmetric key size must
107 // be 0 as well
108 if(in->encryptionKey.t.size != 0)
Vadim Bendebury065e0d72015-10-16 09:35:42 -0700109 return TPM_RC_SIZE + RC_Import_encryptionKey;
Vadim Bendebury56797522015-05-20 10:32:25 -0700110 // If encryptedDuplication is SET, then the object must have an inner
111 // wrapper
112 if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication)
Vadim Bendebury065e0d72015-10-16 09:35:42 -0700113 return TPM_RC_ATTRIBUTES + RC_Import_encryptionKey;
Vadim Bendebury56797522015-05-20 10:32:25 -0700114 }
115
116 // See if there is an outer wrapper
117 if(in->inSymSeed.t.size != 0)
118 {
119 // Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES,
120 // TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT,
121 // TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point
122 result = CryptSecretDecrypt(in->parentHandle, NULL, "DUPLICATE",
123 &in->inSymSeed, &data);
124 pAssert(result != TPM_RC_BINDING);
125//
126 if(result != TPM_RC_SUCCESS)
127 return RcSafeAddToResult(result, RC_Import_inSymSeed);
128 }
129 else
130 {
131 // If encrytpedDuplication is set, then the object must have an outer
132 // wrapper
133 if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication)
Vadim Bendebury065e0d72015-10-16 09:35:42 -0700134 return TPM_RC_ATTRIBUTES + RC_Import_inSymSeed;
Vadim Bendebury56797522015-05-20 10:32:25 -0700135 data.t.size = 0;
136 }
137
138 // Compute name of object
139 ObjectComputeName(&(in->objectPublic.t.publicArea), &name);
140
141 // Retrieve sensitive from private.
142 // TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here.
143 result = DuplicateToSensitive(&in->duplicate, &name, in->parentHandle,
144 in->objectPublic.t.publicArea.nameAlg,
145 (TPM2B_SEED *) &data, &in->symmetricAlg,
146 &in->encryptionKey, &sensitive);
147 if(result != TPM_RC_SUCCESS)
148 return RcSafeAddToResult(result, RC_Import_duplicate);
149
150 // If the parent of this object has fixedTPM SET, then fully validate this
151 // object so that validation can be skipped when it is loaded
152 if(parentObject->publicArea.objectAttributes.fixedTPM == SET)
153 {
154 TPM_HANDLE objectHandle;
155
156 // Perform self check on input public area. A TPM_RC_SIZE, TPM_RC_SCHEME,
157 // TPM_RC_VALUE, TPM_RC_SYMMETRIC, TPM_RC_TYPE, TPM_RC_HASH,
158 // TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES or TPM_RC_KDF error may be returned
159 // at this point
160 result = PublicAttributesValidation(TRUE, in->parentHandle,
161 &in->objectPublic.t.publicArea);
162 if(result != TPM_RC_SUCCESS)
163 return RcSafeAddToResult(result, RC_Import_objectPublic);
164
165 // Create internal object. A TPM_RC_KEY_SIZE, TPM_RC_KEY or
166 // TPM_RC_OBJECT_MEMORY error may be returned at this point
167 result = ObjectLoad(TPM_RH_NULL, &in->objectPublic.t.publicArea,
168 &sensitive, NULL, in->parentHandle, FALSE,
169 &objectHandle);
170 if(result != TPM_RC_SUCCESS)
171 return result;
172
173 // Don't need the object, just needed the checks to be performed so
174 // flush the object
175 ObjectFlush(objectHandle);
176 }
177
178// Command output
179
180 // Prepare output private data from sensitive
181 SensitiveToPrivate(&sensitive, &name, in->parentHandle,
182 in->objectPublic.t.publicArea.nameAlg,
183 &out->outPrivate);
184
185 return TPM_RC_SUCCESS;
186}