• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stefanberger / libtpms / #2063

11 Feb 2026 02:58PM UTC coverage: 77.18% (-0.02%) from 77.195%
#2063

push

travis-ci

web-flow
Merge c175b6f1e into c2a8109f8

1174 of 1370 new or added lines in 95 files covered. (85.69%)

2190 existing lines in 89 files now uncovered.

36347 of 47094 relevant lines covered (77.18%)

125164.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.12
/src/tpm2/TPMCmd/tpm/src/command/Object/CreateLoaded.c
1
// SPDX-License-Identifier: BSD-2-Clause
2

3
#include "Tpm.h"
4
#include "CreateLoaded_fp.h"
5

6
#if CC_CreateLoaded  // Conditional expansion of this file
7

8
/*(See part 3 of specification)
9
 * Create and load any type of key, including a temporary key.
10
 * The input template is a marshaled public area rather than an unmarshaled one as
11
 * used in Create and CreatePrimary. This is so that the label and context that
12
 * could be in the template can be processed without changing the formats for the
13
 * calls to Create and CreatePrimary.
14
*/
15
//  Return Type: TPM_RC
16
//      TPM_RC_ATTRIBUTES       'sensitiveDataOrigin' is CLEAR when 'sensitive.data'
17
//                              is an Empty Buffer;
18
//                              'fixedTPM', 'fixedParent', or 'encryptedDuplication'
19
//                              attributes are inconsistent between themselves or with
20
//                              those of the parent object;
21
//                              inconsistent 'restricted', 'decrypt' and 'sign'
22
//                              attributes;
23
//                              attempt to inject sensitive data for an asymmetric
24
//                              key;
25
//                              attempt to create a symmetric cipher key that is not
26
//                              a decryption key
27
//      TPM_RC_FW_LIMITED       The requested hierarchy is FW-limited, but the TPM
28
//                              does not support FW-limited objects or the TPM failed
29
//                              to derive the Firmware Secret.
30
//      TPM_RC_SVN_LIMITED      The requested hierarchy is SVN-limited, but the TPM
31
//                              does not support SVN-limited objects or the TPM failed
32
//                              to derive the Firmware SVN Secret for the requested
33
//                              SVN.
34
//      TPM_RC_KDF              incorrect KDF specified for decrypting keyed hash
35
//                              object
36
//      TPM_RC_KEY              the value of a provided symmetric key is not allowed
37
//      TPM_RC_OBJECT_MEMORY    there is no free slot for the object
38
//      TPM_RC_SCHEME           inconsistent attributes 'decrypt', 'sign',
39
//                              'restricted' and key's scheme ID; or hash algorithm is
40
//                              inconsistent with the scheme ID for keyed hash object
41
//      TPM_RC_SIZE             size of public authorization policy or sensitive
42
//                              authorization value does not match digest size of the
43
//                              name algorithm sensitive data size for the keyed hash
44
//                              object is larger than is allowed for the scheme
45
//      TPM_RC_SYMMETRIC        a storage key with no symmetric algorithm specified;
46
//                              or non-storage key with symmetric algorithm different
47
//                              from TPM_ALG_NULL
48
//      TPM_RC_TYPE             cannot create the object of the indicated type
49
//                              (usually only occurs if trying to derive an RSA key).
50
TPM_RC
51
TPM2_CreateLoaded(CreateLoaded_In*  in,  // IN: input parameter list
58✔
52
                  CreateLoaded_Out* out  // OUT: output parameter list
53
)
54
{
55
    TPM_RC       result = TPM_RC_SUCCESS;
58✔
56
    OBJECT*      parent = HandleToObject(in->parentHandle);
58✔
57
    OBJECT*      newObject;
58✔
58
    BOOL         derivation;
58✔
59
    TPMT_PUBLIC* publicArea;
58✔
60
    RAND_STATE   randState;
58✔
61
    RAND_STATE*  rand = &randState;
58✔
62
    TPMS_DERIVE  labelContext;
58✔
63
    SEED_COMPAT_LEVEL seedCompatLevel = RuntimeProfileGetSeedCompatLevel(); // libtpms added
58✔
64

65
    // Input Validation
66

67
    // How the public area is unmarshaled is determined by the parent, so
68
    // see if parent is a derivation parent
69
    derivation = (parent != NULL && parent->attributes.derivation);
58✔
70

71
    // If the parent is an object, then make sure that it is either a parent or
72
    // derivation parent
73
    if(parent != NULL && !parent->attributes.isParent && !derivation)
58✔
74
        return TPM_RCS_TYPE + RC_CreateLoaded_parentHandle;
75

76
    // Get a spot in which to create the newObject
77
    newObject = FindEmptyObjectSlot(&out->objectHandle);
58✔
78
    if(newObject == NULL)
58✔
79
        return TPM_RC_OBJECT_MEMORY;
80

81
    // Do this to save typing
82
    publicArea = &newObject->publicArea;
58✔
83

84
    // Unmarshal the template into the object space. TPM2_Create() and
85
    // TPM2_CreatePrimary() have the publicArea unmarshaled by CommandDispatcher.
86
    // This command is different because of an unfortunate property of the
87
    // unique field of an ECC key. It is a structure rather than a single TPM2B. If
88
    // if had been a TPM2B, then the label and context could be within a TPM2B and
89
    // unmarshaled like other public areas. Since it is not, this command needs its
90
    // on template that is a TPM2B that is unmarshaled as a BYTE array with a
91
    // its own unmarshal function.
92
    result = UnmarshalToPublic(publicArea, &in->inPublic, derivation, &labelContext);
58✔
93
    if(result != TPM_RC_SUCCESS)
58✔
NEW
94
        return result + RC_CreateLoaded_inPublic;
×
95

96
    // Validate that the authorization size is appropriate
97
    if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg))
58✔
98
        return TPM_RCS_SIZE + RC_CreateLoaded_inSensitive;
99

100
    // Command output
101
    if(derivation)
58✔
102
    {
103
        TPMT_KEYEDHASH_SCHEME* scheme;
13✔
104
        scheme = &parent->publicArea.parameters.keyedHashDetail.scheme;
13✔
105

106
        // SP800-108 is the only KDF supported by this implementation and there is
107
        // no default hash algorithm.
108
        pAssert_RC(scheme->details.xor.hashAlg != TPM_ALG_NULL
13✔
109
                   && scheme->details.xor.kdf == TPM_ALG_KDF1_SP800_108);
13✔
110
        // Don't derive RSA keys
111
        if(publicArea->type == TPM_ALG_RSA)
13✔
112
            return TPM_RCS_TYPE + RC_CreateLoaded_inPublic;
113
        if(publicArea->type == TPM_ALG_ECC &&                        // libtpms added begin
26✔
114
           RuntimeProfileRequiresAttributeFlags(&g_RuntimeProfile,
13✔
115
                                                RUNTIME_ATTRIBUTE_NO_ECC_KEY_DERIVATION))
116
            return TPM_RCS_TYPE + RC_CreateLoaded_inPublic;                // libtpms added end
117
        // sensitiveDataOrigin has to be CLEAR in a derived object. Since this
118
        // is specific to a derived object, it is checked here.
119
        if(IS_ATTRIBUTE(
13✔
120
               publicArea->objectAttributes, TPMA_OBJECT, sensitiveDataOrigin))
121
            return TPM_RCS_ATTRIBUTES;
122
        // Check the rest of the attributes
123
        result = PublicAttributesValidation(parent, 0, publicArea);
13✔
124
        if(result != TPM_RC_SUCCESS)
13✔
NEW
125
            return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
×
126
        // Process the template and sensitive areas to get the actual 'label' and
127
        // 'context' values to be used for this derivation.
128
        result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data);
13✔
129
        if(result != TPM_RC_SUCCESS)
13✔
130
            return result;
131
        // Set up the KDF for object generation
132
        DRBG_InstantiateSeededKdf((KDF_STATE*)rand,
13✔
133
                                  scheme->details.xor.hashAlg,
13✔
134
                                  scheme->details.xor.kdf,
13✔
135
                                  &parent->sensitive.sensitive.bits.b,
136
                                  &labelContext.label.b,
137
                                  &labelContext.context.b,
138
                                  TPM_MAX_DERIVATION_BITS);
139
        // Clear the sensitive size so that the creation functions will not try
140
        // to use this value.
141
        in->inSensitive.sensitive.data.t.size = 0;
13✔
142
        seedCompatLevel = parent->seedCompatLevel;               // libtpms added
13✔
143
    }
144
    else
145
    {
146
        // Check attributes in input public area. CreateChecks() checks the things
147
        // that are unique to creation and then validates the attributes and values
148
        // that are common to create and load.
149
        result = CreateChecks(parent,
45✔
150
                              (parent == NULL) ? in->parentHandle : 0,
151
                              publicArea,
152
                              in->inSensitive.sensitive.data.t.size);
45✔
153

154
        if(result != TPM_RC_SUCCESS)
45✔
NEW
155
            return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
×
156
        // Creating a primary object
157
        if(parent == NULL)
45✔
158
        {
159
            TPM2B_NAME name;
43✔
160
            TPM2B_SEED primary_seed;
43✔
161

162
            newObject->attributes.primary = SET;
43✔
163
            if(HierarchyNormalizeHandle(in->parentHandle) == TPM_RH_ENDORSEMENT)
43✔
164
                newObject->attributes.epsHierarchy = SET;
12✔
165
            seedCompatLevel = HierarchyGetPrimarySeedCompatLevel(in->parentHandle); // libtpms added 
43✔
166
           // If so, use the primary seed and the digest of the template
167
           // to seed the DRBG
168

169
            result = HierarchyGetPrimarySeed(in->parentHandle, &primary_seed);
43✔
170
            if(result != TPM_RC_SUCCESS)
43✔
NEW
171
                return result;
×
172

173
            // If so, use the primary seed and the digest of the template
174
            // to seed the DRBG
175
            result = DRBG_InstantiateSeeded(
43✔
176
                (DRBG_STATE*)rand,
177
                &primary_seed.b,
178
                PRIMARY_OBJECT_CREATION,
179
                (TPM2B*)PublicMarshalAndComputeName(publicArea, &name),
43✔
180
                &in->inSensitive.sensitive.data.b,
43✔
181
                seedCompatLevel);                                        // libtpms added
182
            MemorySet(primary_seed.b.buffer, 0, primary_seed.b.size);
43✔
183

184
            if(result != TPM_RC_SUCCESS)
43✔
185
                return result;
186
        }
187
        else
188
        {
189
            // This is an ordinary object so use the normal random number generator
190
            rand = NULL;
191
        }
192
    }
193
    // Internal data update
194
    // Create the object
195
    result = CryptCreateObject(newObject, &in->inSensitive.sensitive, rand);
58✔
196
    DRBG_Uninstantiate((DRBG_STATE*)rand);
58✔
197
    if(result != TPM_RC_SUCCESS)
58✔
198
        return result;
199
    // if this is not a Primary key and not a derived key, then return the sensitive
200
    // area
201
    if(parent != NULL && !derivation)
58✔
202
    {
203
        // Prepare output private data from sensitive
204
        result = SensitiveToPrivate(&newObject->sensitive,
2✔
205
                                    &newObject->name,
206
                                    parent,
207
                                    newObject->publicArea.nameAlg,
2✔
208
                                    &out->outPrivate);
209
    }
210
    else
211
    {
212
        out->outPrivate.t.size = 0;
56✔
213
    }
214
    // Set the remaining return values
215
    out->outPublic.publicArea = newObject->publicArea;
58✔
216
    out->name                 = newObject->name;
58✔
217
    // Set the remaining attributes for a loaded object
218
    ObjectSetLoadedAttributes(newObject, in->parentHandle,
58✔
219
                              seedCompatLevel);                                // libtpms added
220
    return result;
58✔
221
}
222

223
#endif  // CC_CreateLoaded
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc