• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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