blob: e022d08b1b8afa7ddc948392435f200e0e1eb2d0 [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// 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//
26TPM_RC
27TPM2_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
Vadim Bendebury30f6dee2015-05-29 22:51:10 -070092 out->outSymSeed.t.size = sizeof(out->outSymSeed.t.buffer);
Vadim Bendebury56797522015-05-20 10:32:25 -070093 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}