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
TPM2_Duplicate(Duplicate_In * in,Duplicate_Out * out)27 TPM2_Duplicate(
28 Duplicate_In *in, // IN: input parameter list
29 Duplicate_Out *out // OUT: output parameter list
30 )
31 {
32 TPM_RC result = TPM_RC_SUCCESS;
33 TPMT_SENSITIVE sensitive;
34
35 UINT16 innerKeySize = 0; // encrypt key size for inner wrap
36
37 OBJECT *object;
38 TPM2B_DATA data;
39
40 // Input Validation
41
42 // Get duplicate object pointer
43 object = ObjectGet(in->objectHandle);
44
45 // duplicate key must have fixParent bit CLEAR.
46 if(object->publicArea.objectAttributes.fixedParent == SET)
47 return TPM_RC_ATTRIBUTES + RC_Duplicate_objectHandle;
48
49 // Do not duplicate object with NULL nameAlg
50 if(object->publicArea.nameAlg == TPM_ALG_NULL)
51 return TPM_RC_TYPE + RC_Duplicate_objectHandle;
52
53 // new parent key must be a storage object or TPM_RH_NULL
54 if(in->newParentHandle != TPM_RH_NULL
55 && !ObjectIsStorage(in->newParentHandle))
56 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 if(object->publicArea.objectAttributes.encryptedDuplication == SET)
61 {
62 if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
63 return TPM_RC_SYMMETRIC + RC_Duplicate_symmetricAlg;
64 if(in->newParentHandle == TPM_RH_NULL)
65 return TPM_RC_HIERARCHY + RC_Duplicate_newParentHandle;
66 }
67
68 if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
69 {
70 // if algorithm is TPM_ALG_NULL, input key size must be 0
71 if(in->encryptionKeyIn.t.size != 0)
72 return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
73 }
74 else
75 {
76 // Get inner wrap key size
77 innerKeySize = in->symmetricAlg.keyBits.sym;
78
79 // If provided the input symmetric key must match the size of the algorithm
80 if(in->encryptionKeyIn.t.size != 0
81 && in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8)
82 return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
83 }
84
85 // Command Output
86
87 if(in->newParentHandle != TPM_RH_NULL)
88 {
89
90 // Make encrypt key and its associated secret structure. A TPM_RC_KEY
91 // error may be returned at this point
92 out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
93 result = CryptSecretEncrypt(in->newParentHandle,
94 "DUPLICATE", &data, &out->outSymSeed);
95 pAssert(result != TPM_RC_VALUE);
96 if(result != TPM_RC_SUCCESS)
97 return result;
98 }
99 else
100 {
101 // Do not apply outer wrapper
102 data.t.size = 0;
103 out->outSymSeed.t.size = 0;
104 }
105
106 // Copy sensitive area
107 sensitive = object->sensitive;
108
109 // Prepare output private data from sensitive
110 SensitiveToDuplicate(&sensitive, &object->name, in->newParentHandle,
111 object->publicArea.nameAlg, (TPM2B_SEED *) &data,
112 &in->symmetricAlg, &in->encryptionKeyIn,
113 &out->duplicate);
114
115 out->encryptionKeyOut = in->encryptionKeyIn;
116
117 return TPM_RC_SUCCESS;
118 }
119