1 /* Microsoft Reference Implementation for TPM 2.0
2 *
3 * The copyright in this software is being made available under the BSD License,
4 * included below. This software may be subject to other third party and
5 * contributor rights, including patent rights, and no such rights are granted
6 * under this license.
7 *
8 * Copyright (c) Microsoft Corporation
9 *
10 * All rights reserved.
11 *
12 * BSD License
13 *
14 * Redistribution and use in source and binary forms, with or without modification,
15 * are permitted provided that the following conditions are met:
16 *
17 * Redistributions of source code must retain the above copyright notice, this list
18 * of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright notice, this
21 * list of conditions and the following disclaimer in the documentation and/or
22 * other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35 #include "Tpm.h"
36 #include "CreateLoaded_fp.h"
37
38 #if CC_CreateLoaded // Conditional expansion of this file
39
40 /*(See part 3 of specification)
41 * Create and load any type of key, including a temporary key.
42 * The input template is a marshaled public area rather than an unmarshaled one as
43 * used in Create and CreatePrimary. This is so that the label and context that
44 * could be in the template can be processed without changing the formats for the
45 * calls to Create and CreatePrimary.
46 */
47 // Return Type: TPM_RC
48 // TPM_RC_ATTRIBUTES 'sensitiveDataOrigin' is CLEAR when 'sensitive.data'
49 // is an Empty Buffer;
50 // 'fixedTPM', 'fixedParent', or 'encryptedDuplication'
51 // attributes are inconsistent between themselves or with
52 // those of the parent object;
53 // inconsistent 'restricted', 'decrypt' and 'sign'
54 // attributes;
55 // attempt to inject sensitive data for an asymmetric
56 // key;
57 // attempt to create a symmetric cipher key that is not
58 // a decryption key
59 // TPM_RC_KDF incorrect KDF specified for decrypting keyed hash
60 // object
61 // TPM_RC_KEY the value of a provided symmetric key is not allowed
62 // TPM_RC_OBJECT_MEMORY there is no free slot for the object
63 // TPM_RC_SCHEME inconsistent attributes 'decrypt', 'sign',
64 // 'restricted' and key's scheme ID; or hash algorithm is
65 // inconsistent with the scheme ID for keyed hash object
66 // TPM_RC_SIZE size of public authorization policy or sensitive
67 // authorization value does not match digest size of the
68 // name algorithm sensitive data size for the keyed hash
69 // object is larger than is allowed for the scheme
70 // TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified;
71 // or non-storage key with symmetric algorithm different
72 // from TPM_ALG_NULL
73 // TPM_RC_TYPE cannot create the object of the indicated type
74 // (usually only occurs if trying to derive an RSA key).
75 TPM_RC
TPM2_CreateLoaded(CreateLoaded_In * in,CreateLoaded_Out * out)76 TPM2_CreateLoaded(
77 CreateLoaded_In *in, // IN: input parameter list
78 CreateLoaded_Out *out // OUT: output parameter list
79 )
80 {
81 TPM_RC result = TPM_RC_SUCCESS;
82 OBJECT *parent = HandleToObject(in->parentHandle);
83 OBJECT *newObject;
84 BOOL derivation;
85 TPMT_PUBLIC *publicArea;
86 RAND_STATE randState;
87 RAND_STATE *rand = &randState;
88 TPMS_DERIVE labelContext;
89
90 // Input Validation
91
92 // How the public area is unmarshaled is determined by the parent, so
93 // see if parent is a derivation parent
94 derivation = (parent != NULL && parent->attributes.derivation);
95
96 // If the parent is an object, then make sure that it is either a parent or
97 // derivation parent
98 if(parent != NULL && !parent->attributes.isParent && !derivation)
99 return TPM_RCS_TYPE + RC_CreateLoaded_parentHandle;
100
101 // Get a spot in which to create the newObject
102 newObject = FindEmptyObjectSlot(&out->objectHandle);
103 if(newObject == NULL)
104 return TPM_RC_OBJECT_MEMORY;
105
106 // Do this to save typing
107 publicArea = &newObject->publicArea;
108
109 // Unmarshal the template into the object space. TPM2_Create() and
110 // TPM2_CreatePrimary() have the publicArea unmarshaled by CommandDispatcher.
111 // This command is different because of an unfortunate property of the
112 // unique field of an ECC key. It is a structure rather than a single TPM2B. If
113 // if had been a TPM2B, then the label and context could be within a TPM2B and
114 // unmarshaled like other public areas. Since it is not, this command needs its
115 // on template that is a TPM2B that is unmarshaled as a BYTE array with a
116 // its own unmarshal function.
117 result = UnmarshalToPublic(publicArea, &in->inPublic, derivation,
118 &labelContext);
119 if(result != TPM_RC_SUCCESS)
120 return result + RC_CreateLoaded_inPublic;
121
122 // Validate that the authorization size is appropriate
123 if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg))
124 return TPM_RCS_SIZE + RC_CreateLoaded_inSensitive;
125
126 // Command output
127 if(derivation)
128 {
129 TPMT_KEYEDHASH_SCHEME *scheme;
130 scheme = &parent->publicArea.parameters.keyedHashDetail.scheme;
131
132 // SP800-108 is the only KDF supported by this implementation and there is
133 // no default hash algorithm.
134 pAssert(scheme->details.xor.hashAlg != TPM_ALG_NULL
135 && scheme->details.xor.kdf == TPM_ALG_KDF1_SP800_108);
136 // Don't derive RSA keys
137 if(publicArea->type == TPM_ALG_RSA)
138 return TPM_RCS_TYPE + RC_CreateLoaded_inPublic;
139 // sensitiveDataOrigin has to be CLEAR in a derived object. Since this
140 // is specific to a derived object, it is checked here.
141 if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT,
142 sensitiveDataOrigin))
143 return TPM_RCS_ATTRIBUTES;
144 // Check the reset of the attributes
145 result = PublicAttributesValidation(parent, publicArea);
146 if(result != TPM_RC_SUCCESS)
147 return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
148 // Process the template and sensitive areas to get the actual 'label' and
149 // 'context' values to be used for this derivation.
150 result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data);
151 if(result != TPM_RC_SUCCESS)
152 return result;
153 // Set up the KDF for object generation
154 DRBG_InstantiateSeededKdf((KDF_STATE *)rand,
155 scheme->details.xor.hashAlg,
156 scheme->details.xor.kdf,
157 &parent->sensitive.sensitive.bits.b,
158 &labelContext.label.b,
159 &labelContext.context.b,
160 TPM_MAX_DERIVATION_BITS);
161 // Clear the sensitive size so that the creation functions will not try
162 // to use this value.
163 in->inSensitive.sensitive.data.t.size = 0;
164 }
165 else
166 {
167 // Check attributes in input public area. CreateChecks() checks the things
168 // that are unique to creation and then validates the attributes and values
169 // that are common to create and load.
170 result = CreateChecks(parent, publicArea,
171 in->inSensitive.sensitive.data.t.size);
172 if(result != TPM_RC_SUCCESS)
173 return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
174 // Creating a primary object
175 if(parent == NULL)
176 {
177 TPM2B_NAME name;
178 newObject->attributes.primary = SET;
179 if(in->parentHandle == TPM_RH_ENDORSEMENT)
180 newObject->attributes.epsHierarchy = SET;
181 // If so, use the primary seed and the digest of the template
182 // to seed the DRBG
183 result = DRBG_InstantiateSeeded((DRBG_STATE *)rand,
184 &HierarchyGetPrimarySeed(in->parentHandle)->b,
185 PRIMARY_OBJECT_CREATION,
186 (TPM2B *)PublicMarshalAndComputeName(publicArea,
187 &name),
188 &in->inSensitive.sensitive.data.b);
189 if(result != TPM_RC_SUCCESS)
190 return result;
191 }
192 else
193 {
194 // This is an ordinary object so use the normal random number generator
195 rand = NULL;
196 }
197 }
198 // Internal data update
199 // Create the object
200 result = CryptCreateObject(newObject, &in->inSensitive.sensitive, rand);
201 if(result != TPM_RC_SUCCESS)
202 return result;
203 // if this is not a Primary key and not a derived key, then return the sensitive
204 // area
205 if(parent != NULL && !derivation)
206 // Prepare output private data from sensitive
207 SensitiveToPrivate(&newObject->sensitive, &newObject->name,
208 parent, newObject->publicArea.nameAlg,
209 &out->outPrivate);
210 else
211 out->outPrivate.t.size = 0;
212 // Set the remaining return values
213 out->outPublic.publicArea = newObject->publicArea;
214 out->name = newObject->name;
215 // Set the remaining attributes for a loaded object
216 ObjectSetLoadedAttributes(newObject, in->parentHandle);
217
218 return result;
219 }
220
221 #endif // CC_CreateLoaded