Coverage Report

Created: 2026-04-01 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ibmswtpm2/src/DuplicationCommands.c
Line
Count
Source
1
/********************************************************************************/
2
/*                    */
3
/*          Duplication Commands        */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*            $Id: DuplicationCommands.c 1259 2018-07-10 19:11:09Z kgoldman $ */
7
/*                    */
8
/*  Licenses and Notices              */
9
/*                    */
10
/*  1. Copyright Licenses:              */
11
/*                    */
12
/*  - Trusted Computing Group (TCG) grants to the user of the source code in  */
13
/*    this specification (the "Source Code") a worldwide, irrevocable,    */
14
/*    nonexclusive, royalty free, copyright license to reproduce, create  */
15
/*    derivative works, distribute, display and perform the Source Code and */
16
/*    derivative works thereof, and to grant others the rights granted herein.  */
17
/*                    */
18
/*  - The TCG grants to the user of the other parts of the specification  */
19
/*    (other than the Source Code) the rights to reproduce, distribute,   */
20
/*    display, and perform the specification solely for the purpose of    */
21
/*    developing products based on such documents.        */
22
/*                    */
23
/*  2. Source Code Distribution Conditions:         */
24
/*                    */
25
/*  - Redistributions of Source Code must retain the above copyright licenses,  */
26
/*    this list of conditions and the following disclaimers.      */
27
/*                    */
28
/*  - Redistributions in binary form must reproduce the above copyright   */
29
/*    licenses, this list of conditions and the following disclaimers in the  */
30
/*    documentation and/or other materials provided with the distribution.  */
31
/*                    */
32
/*  3. Disclaimers:               */
33
/*                    */
34
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
35
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
36
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
37
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.   */
38
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for    */
39
/*  information on specification licensing rights available through TCG   */
40
/*  membership agreements.              */
41
/*                    */
42
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED   */
43
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR   */
44
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR    */
45
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY    */
46
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.   */
47
/*                    */
48
/*  - Without limitation, TCG and its members and licensors disclaim all  */
49
/*    liability, including liability for infringement of any proprietary  */
50
/*    rights, relating to use of information in this specification and to the */
51
/*    implementation of this specification, and TCG disclaims all liability for */
52
/*    cost of procurement of substitute goods or services, lost profits, loss   */
53
/*    of use, loss of data or any incidental, consequential, direct, indirect,  */
54
/*    or special damages, whether under contract, tort, warranty or otherwise,  */
55
/*    arising in any way out of use or reliance upon this specification or any  */
56
/*    information herein.             */
57
/*                    */
58
/*  (c) Copyright IBM Corp. and others, 2016 - 2018       */
59
/*                    */
60
/********************************************************************************/
61
62
#include "Tpm.h"
63
#include "Duplicate_fp.h"
64
#if CC_Duplicate  // Conditional expansion of this file
65
#include "Object_spt_fp.h"
66
TPM_RC
67
TPM2_Duplicate(
68
         Duplicate_In    *in,            // IN: input parameter list
69
         Duplicate_Out   *out            // OUT: output parameter list
70
         )
71
0
{
72
0
    TPM_RC                  result = TPM_RC_SUCCESS;
73
0
    TPMT_SENSITIVE          sensitive;
74
0
    UINT16                  innerKeySize = 0; // encrypt key size for inner wrap
75
0
    OBJECT                  *object;
76
0
    OBJECT                  *newParent;
77
0
    TPM2B_DATA              data;
78
    // Input Validation
79
    // Get duplicate object pointer
80
0
    object = HandleToObject(in->objectHandle);
81
    // Get new parent
82
0
    newParent = HandleToObject(in->newParentHandle);
83
    // duplicate key must have fixParent bit CLEAR.
84
0
    if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, fixedParent))
85
0
  return TPM_RCS_ATTRIBUTES + RC_Duplicate_objectHandle;
86
    // Do not duplicate object with NULL nameAlg
87
0
    if(object->publicArea.nameAlg == TPM_ALG_NULL)
88
0
  return TPM_RCS_TYPE + RC_Duplicate_objectHandle;
89
    // new parent key must be a storage object or TPM_RH_NULL
90
0
    if(in->newParentHandle != TPM_RH_NULL
91
0
       && !ObjectIsStorage(in->newParentHandle))
92
0
  return TPM_RCS_TYPE + RC_Duplicate_newParentHandle;
93
    // If the duplicated object has encryptedDuplication SET, then there must be
94
    // an inner wrapper and the new parent may not be TPM_RH_NULL
95
0
    if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT,
96
0
        encryptedDuplication))
97
0
  {
98
0
      if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
99
0
    return TPM_RCS_SYMMETRIC + RC_Duplicate_symmetricAlg;
100
0
      if(in->newParentHandle == TPM_RH_NULL)
101
0
    return TPM_RCS_HIERARCHY + RC_Duplicate_newParentHandle;
102
0
  }
103
0
    if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
104
0
  {
105
      // if algorithm is TPM_ALG_NULL, input key size must be 0
106
0
      if(in->encryptionKeyIn.t.size != 0)
107
0
    return TPM_RCS_SIZE + RC_Duplicate_encryptionKeyIn;
108
0
  }
109
0
    else
110
0
  {
111
      // Get inner wrap key size
112
0
      innerKeySize = in->symmetricAlg.keyBits.sym;
113
      // If provided the input symmetric key must match the size of the algorithm
114
0
      if(in->encryptionKeyIn.t.size != 0
115
0
         && in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8)
116
0
    return TPM_RCS_SIZE + RC_Duplicate_encryptionKeyIn;
117
0
  }
118
    // Command Output
119
0
    if(in->newParentHandle != TPM_RH_NULL)
120
0
  {
121
      // Make encrypt key and its associated secret structure.  A TPM_RC_KEY
122
      // error may be returned at this point
123
0
      out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
124
0
      result = CryptSecretEncrypt(newParent, DUPLICATE_STRING, &data,
125
0
          &out->outSymSeed);
126
0
      if(result != TPM_RC_SUCCESS)
127
0
    return result;
128
0
  }
129
0
    else
130
0
  {
131
      // Do not apply outer wrapper
132
0
      data.t.size = 0;
133
0
      out->outSymSeed.t.size = 0;
134
0
  }
135
    // Copy sensitive area
136
0
    sensitive = object->sensitive;
137
    // Prepare output private data from sensitive.
138
    // Note: If there is no encryption key, one will be provided by
139
    // SensitiveToDuplicate(). This is why the assignment of encryptionKeyIn to
140
    // encryptionKeyOut will work properly and is not conditional.
141
0
    SensitiveToDuplicate(&sensitive, &object->name.b, newParent,
142
0
       object->publicArea.nameAlg, &data.b,
143
0
       &in->symmetricAlg, &in->encryptionKeyIn,
144
0
       &out->duplicate);
145
0
    out->encryptionKeyOut = in->encryptionKeyIn;
146
0
    return TPM_RC_SUCCESS;
147
0
}
148
#endif // CC_Duplicate
149
#include "Tpm.h"
150
#include "Rewrap_fp.h"
151
#if CC_Rewrap  // Conditional expansion of this file
152
#include "Object_spt_fp.h"
153
TPM_RC
154
TPM2_Rewrap(
155
      Rewrap_In       *in,            // IN: input parameter list
156
      Rewrap_Out      *out            // OUT: output parameter list
157
      )
158
0
{
159
0
    TPM_RC                  result = TPM_RC_SUCCESS;
160
0
    TPM2B_DATA              data;               // symmetric key
161
0
    UINT16                  hashSize = 0;
162
0
    TPM2B_PRIVATE           privateBlob;        // A temporary private blob
163
    // to transit between old
164
    // and new wrappers
165
    // Input Validation
166
0
    if((in->inSymSeed.t.size == 0 && in->oldParent != TPM_RH_NULL)
167
0
       || (in->inSymSeed.t.size != 0 && in->oldParent == TPM_RH_NULL))
168
0
  return TPM_RCS_HANDLE + RC_Rewrap_oldParent;
169
0
    if(in->oldParent != TPM_RH_NULL)
170
0
  {
171
0
      OBJECT              *oldParent = HandleToObject(in->oldParent);
172
      // old parent key must be a storage object
173
0
      if(!ObjectIsStorage(in->oldParent))
174
0
    return TPM_RCS_TYPE + RC_Rewrap_oldParent;
175
      // Decrypt input secret data via asymmetric decryption.  A
176
      // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
177
      // point
178
0
      result = CryptSecretDecrypt(oldParent, NULL, DUPLICATE_STRING,
179
0
          &in->inSymSeed, &data);
180
0
      if(result != TPM_RC_SUCCESS)
181
0
    return TPM_RCS_VALUE + RC_Rewrap_inSymSeed;
182
      // Unwrap Outer
183
0
      result = UnwrapOuter(oldParent, &in->name.b,
184
0
         oldParent->publicArea.nameAlg, &data.b,
185
0
         FALSE,
186
0
         in->inDuplicate.t.size, in->inDuplicate.t.buffer);
187
0
      if(result != TPM_RC_SUCCESS)
188
0
    return RcSafeAddToResult(result, RC_Rewrap_inDuplicate);
189
      // Copy unwrapped data to temporary variable, remove the integrity field
190
0
      hashSize = sizeof(UINT16) +
191
0
           CryptHashGetDigestSize(oldParent->publicArea.nameAlg);
192
0
      privateBlob.t.size = in->inDuplicate.t.size - hashSize;
193
0
      pAssert(privateBlob.t.size <= sizeof(privateBlob.t.buffer));
194
0
      MemoryCopy(privateBlob.t.buffer, in->inDuplicate.t.buffer + hashSize,
195
0
           privateBlob.t.size);
196
0
  }
197
0
    else
198
0
  {
199
      // No outer wrap from input blob.  Direct copy.
200
0
      privateBlob = in->inDuplicate;
201
0
  }
202
0
    if(in->newParent != TPM_RH_NULL)
203
0
  {
204
0
      OBJECT          *newParent;
205
0
      newParent = HandleToObject(in->newParent);
206
      // New parent must be a storage object
207
0
      if(!ObjectIsStorage(in->newParent))
208
0
    return TPM_RCS_TYPE + RC_Rewrap_newParent;
209
      // Make new encrypt key and its associated secret structure.  A
210
      // TPM_RC_VALUE error may be returned at this point if RSA algorithm is
211
      // enabled in TPM
212
0
      out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
213
0
      result = CryptSecretEncrypt(newParent, DUPLICATE_STRING, &data,
214
0
          &out->outSymSeed);
215
0
      if(result != TPM_RC_SUCCESS)
216
0
    return result;
217
      // Copy temporary variable to output, reserve the space for integrity
218
0
      hashSize = sizeof(UINT16) +
219
0
           CryptHashGetDigestSize(newParent->publicArea.nameAlg);
220
      // Make sure that everything fits into the output buffer
221
      // Note: this is mostly only an issue if there was no outer wrapper on
222
      // 'inDuplicate'. It could be as large as a TPM2B_PRIVATE buffer. If we add
223
      // a digest for an outer wrapper, it won't fit anymore.
224
0
      if((privateBlob.t.size + hashSize) > sizeof(out->outDuplicate.t.buffer))
225
0
    return TPM_RCS_VALUE + RC_Rewrap_inDuplicate;
226
      // Command output
227
0
      out->outDuplicate.t.size = privateBlob.t.size;
228
0
      pAssert(privateBlob.t.size
229
0
        <= sizeof(out->outDuplicate.t.buffer) - hashSize);
230
0
      MemoryCopy(out->outDuplicate.t.buffer + hashSize, privateBlob.t.buffer,
231
0
           privateBlob.t.size);
232
      // Produce outer wrapper for output
233
0
      out->outDuplicate.t.size = ProduceOuterWrap(newParent, &in->name.b,
234
0
              newParent->publicArea.nameAlg,
235
0
              &data.b,
236
0
              FALSE,
237
0
              out->outDuplicate.t.size,
238
0
              out->outDuplicate.t.buffer);
239
0
  }
240
0
    else  // New parent is a null key so there is no seed
241
0
  {
242
0
      out->outSymSeed.t.size = 0;
243
      // Copy privateBlob directly
244
0
      out->outDuplicate = privateBlob;
245
0
  }
246
0
    return TPM_RC_SUCCESS;
247
0
}
248
#endif // CC_Rewrap
249
#include "Tpm.h"
250
#include "Import_fp.h"
251
#if CC_Import  // Conditional expansion of this file
252
#include "Object_spt_fp.h"
253
TPM_RC
254
TPM2_Import(
255
      Import_In       *in,            // IN: input parameter list
256
      Import_Out      *out            // OUT: output parameter list
257
      )
258
0
{
259
0
    TPM_RC                   result = TPM_RC_SUCCESS;
260
0
    OBJECT                  *parentObject;
261
0
    TPM2B_DATA               data;                   // symmetric key
262
0
    TPMT_SENSITIVE           sensitive;
263
0
    TPM2B_NAME               name;
264
0
    TPMA_OBJECT              attributes;
265
0
    UINT16                   innerKeySize = 0;       // encrypt key size for inner
266
    // wrapper
267
    // Input Validation
268
    // to save typing
269
0
    attributes = in->objectPublic.publicArea.objectAttributes;
270
    // FixedTPM and fixedParent must be CLEAR
271
0
    if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)
272
0
       || IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent))
273
0
  return TPM_RCS_ATTRIBUTES + RC_Import_objectPublic;
274
    // Get parent pointer
275
0
    parentObject = HandleToObject(in->parentHandle);
276
0
    if(!ObjectIsParent(parentObject))
277
0
  return TPM_RCS_TYPE + RC_Import_parentHandle;
278
0
    if(in->symmetricAlg.algorithm != TPM_ALG_NULL)
279
0
  {
280
      // Get inner wrap key size
281
0
      innerKeySize = in->symmetricAlg.keyBits.sym;
282
      // Input symmetric key must match the size of algorithm.
283
0
      if(in->encryptionKey.t.size != (innerKeySize + 7) / 8)
284
0
    return TPM_RCS_SIZE + RC_Import_encryptionKey;
285
0
  }
286
0
    else
287
0
  {
288
      // If input symmetric algorithm is NULL, input symmetric key size must
289
      // be 0 as well
290
0
      if(in->encryptionKey.t.size != 0)
291
0
    return TPM_RCS_SIZE + RC_Import_encryptionKey;
292
      // If encryptedDuplication is SET, then the object must have an inner
293
      // wrapper
294
0
      if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
295
0
    return TPM_RCS_ATTRIBUTES + RC_Import_encryptionKey;
296
0
  }
297
    // See if there is an outer wrapper
298
0
    if(in->inSymSeed.t.size != 0)
299
0
  {
300
      // in->inParentHandle is a parent, but in order to decrypt an outer wrapper,
301
      // it must be able to do key exchange and a symmetric key can't do that.
302
0
      if(parentObject->publicArea.type == TPM_ALG_SYMCIPHER)
303
0
    return TPM_RCS_TYPE + RC_Import_parentHandle;
304
      // Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES,
305
      // TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT,
306
      // TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point
307
0
      result = CryptSecretDecrypt(parentObject, NULL, DUPLICATE_STRING,
308
0
          &in->inSymSeed, &data);
309
0
      pAssert(result != TPM_RC_BINDING);
310
0
      if(result != TPM_RC_SUCCESS)
311
0
    return RcSafeAddToResult(result, RC_Import_inSymSeed);
312
0
  }
313
0
    else
314
0
  {
315
      // If encrytpedDuplication is set, then the object must have an outer
316
      // wrapper
317
0
      if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
318
0
    return TPM_RCS_ATTRIBUTES + RC_Import_inSymSeed;
319
0
      data.t.size = 0;
320
0
  }
321
    // Compute name of object
322
0
    PublicMarshalAndComputeName(&(in->objectPublic.publicArea), &name);
323
0
    if(name.t.size == 0)
324
0
  return TPM_RCS_HASH + RC_Import_objectPublic;
325
    // Retrieve sensitive from private.
326
    // TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here.
327
0
    result = DuplicateToSensitive(&in->duplicate.b, &name.b, parentObject,
328
0
          in->objectPublic.publicArea.nameAlg,
329
0
          &data.b, &in->symmetricAlg,
330
0
          &in->encryptionKey.b, &sensitive);
331
0
    if(result != TPM_RC_SUCCESS)
332
0
  return RcSafeAddToResult(result, RC_Import_duplicate);
333
    // If the parent of this object has fixedTPM SET, then validate this
334
    // object as if it were being loaded so that validation can be skipped
335
    // when it is actually loaded.
336
0
    if(IS_ATTRIBUTE(parentObject->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM))
337
0
  {
338
0
      result = ObjectLoad(NULL, NULL, &in->objectPublic.publicArea,
339
0
        &sensitive, RC_Import_objectPublic, RC_Import_duplicate,
340
0
        NULL);
341
0
  }
342
    // Command output
343
0
    if(result == TPM_RC_SUCCESS)
344
0
  {
345
      // Prepare output private data from sensitive
346
0
      SensitiveToPrivate(&sensitive, &name.b, parentObject,
347
0
             in->objectPublic.publicArea.nameAlg,
348
0
             &out->outPrivate);
349
0
  }
350
0
    return result;
351
0
}
352
#endif // CC_Import