Coverage Report

Created: 2025-11-29 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tpm2/Duplicate.c
Line
Count
Source
1
// 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 "Duplicate_fp.h"
10
#include "Object_spt_fp.h"
11
//
12
//
13
//     Error Returns                Meaning
14
//
15
//     TPM_RC_ATTRIBUTES            key to duplicate has fixedParent SET
16
//     TPM_RC_HIERARCHY             encryptedDuplication is SET and newParentHandle specifies Null
17
//                                  Hierarchy
18
//     TPM_RC_KEY                   newParentHandle references invalid ECC key (public point not on the
19
//                                  curve)
20
//     TPM_RC_SIZE                  input encryption key size does not match the size specified in
21
//                                  symmetric algorithm
22
//     TPM_RC_SYMMETRIC             encryptedDuplication is SET but no symmetric algorithm is provided
23
//     TPM_RC_TYPE                  newParentHandle is neither a storage key nor TPM_RH_NULL; or
24
//                                  the object has a NULL nameAlg
25
//
26
TPM_RC
27
TPM2_Duplicate(
28
   Duplicate_In      *in,            // IN: input parameter list
29
   Duplicate_Out     *out            // OUT: output parameter list
30
   )
31
0
{
32
0
   TPM_RC                   result = TPM_RC_SUCCESS;
33
0
   TPMT_SENSITIVE           sensitive;
34
35
0
   UINT16                   innerKeySize = 0; // encrypt key size for inner wrap
36
37
0
   OBJECT                   *object;
38
0
   TPM2B_DATA               data;
39
40
// Input Validation
41
42
   // Get duplicate object pointer
43
0
   object = ObjectGet(in->objectHandle);
44
45
   // duplicate key must have fixParent bit CLEAR.
46
0
   if(object->publicArea.objectAttributes.fixedParent == SET)
47
0
       return TPM_RC_ATTRIBUTES + RC_Duplicate_objectHandle;
48
49
   // Do not duplicate object with NULL nameAlg
50
0
   if(object->publicArea.nameAlg == TPM_ALG_NULL)
51
0
       return TPM_RC_TYPE + RC_Duplicate_objectHandle;
52
53
   // new parent key must be a storage object or TPM_RH_NULL
54
0
   if(in->newParentHandle != TPM_RH_NULL
55
0
           && !ObjectIsStorage(in->newParentHandle))
56
0
       return TPM_RC_TYPE + RC_Duplicate_newParentHandle;
57
58
   // If the duplicates object has encryptedDuplication SET, then there must be
59
   // an inner wrapper and the new parent may not be TPM_RH_NULL
60
0
   if(object->publicArea.objectAttributes.encryptedDuplication == SET)
61
0
   {
62
0
       if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
63
0
           return TPM_RC_SYMMETRIC + RC_Duplicate_symmetricAlg;
64
0
       if(in->newParentHandle == TPM_RH_NULL)
65
0
            return TPM_RC_HIERARCHY + RC_Duplicate_newParentHandle;
66
0
   }
67
68
0
   if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
69
0
   {
70
       // if algorithm is TPM_ALG_NULL, input key size must be 0
71
0
       if(in->encryptionKeyIn.t.size != 0)
72
0
           return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
73
0
   }
74
0
   else
75
0
   {
76
       // Get inner wrap key size
77
0
       innerKeySize = in->symmetricAlg.keyBits.sym;
78
79
       // If provided the input symmetric key must match the size of the algorithm
80
0
       if(in->encryptionKeyIn.t.size != 0
81
0
               && in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8)
82
0
           return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
83
0
   }
84
85
// Command Output
86
87
0
   if(in->newParentHandle != TPM_RH_NULL)
88
0
   {
89
90
       // Make encrypt key and its associated secret structure. A TPM_RC_KEY
91
       // error may be returned at this point
92
0
       out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
93
0
       result = CryptSecretEncrypt(in->newParentHandle,
94
0
                                   "DUPLICATE", &data, &out->outSymSeed);
95
0
       pAssert(result != TPM_RC_VALUE);
96
0
       if(result != TPM_RC_SUCCESS)
97
0
           return result;
98
0
   }
99
0
   else
100
0
   {
101
       // Do not apply outer wrapper
102
0
       data.t.size = 0;
103
0
       out->outSymSeed.t.size = 0;
104
0
   }
105
106
   // Copy sensitive area
107
0
   sensitive = object->sensitive;
108
109
   // Prepare output private data from sensitive
110
0
   SensitiveToDuplicate(&sensitive, &object->name, in->newParentHandle,
111
0
                        object->publicArea.nameAlg, (TPM2B_SEED *) &data,
112
0
                        &in->symmetricAlg, &in->encryptionKeyIn,
113
0
                        &out->duplicate);
114
115
0
   out->encryptionKeyOut = in->encryptionKeyIn;
116
117
0
   return TPM_RC_SUCCESS;
118
0
}