1 /* Microsoft Reference Implementation for TPM 2.0
2 *
3 * The copyright in this software is being made available under the BSD License,
4 * included below. This software may be subject to other third party and
5 * contributor rights, including patent rights, and no such rights are granted
6 * under this license.
7 *
8 * Copyright (c) Microsoft Corporation
9 *
10 * All rights reserved.
11 *
12 * BSD License
13 *
14 * Redistribution and use in source and binary forms, with or without modification,
15 * are permitted provided that the following conditions are met:
16 *
17 * Redistributions of source code must retain the above copyright notice, this list
18 * of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright notice, this
21 * list of conditions and the following disclaimer in the documentation and/or
22 * other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35 #include "Tpm.h"
36 #include "Import_fp.h"
37
38 #if CC_Import // Conditional expansion of this file
39
40 #include "Object_spt_fp.h"
41
42 /*(See part 3 specification)
43 // This command allows an asymmetrically encrypted blob, containing a duplicated
44 // object to be re-encrypted using the group symmetric key associated with the
45 // parent.
46 */
47 // Return Type: TPM_RC
48 // TPM_RC_ATTRIBUTES 'FixedTPM' and 'fixedParent' of 'objectPublic' are not
49 // both CLEAR; or 'inSymSeed' is nonempty and
50 // 'parentHandle' does not reference a decryption key; or
51 // 'objectPublic' and 'parentHandle' have incompatible
52 // or inconsistent attributes; or
53 // encrytpedDuplication is SET in 'objectPublic' but the
54 // inner or outer wrapper is missing.
55 // Note that if the TPM provides parameter values, the
56 // parameter number will indicate 'symmetricKey' (missing
57 // inner wrapper) or 'inSymSeed' (missing outer wrapper)
58 // TPM_RC_BINDING 'duplicate' and 'objectPublic' are not
59 // cryptographically bound
60 // TPM_RC_ECC_POINT 'inSymSeed' is nonempty and ECC point in 'inSymSeed'
61 // is not on the curve
62 // TPM_RC_HASH 'objectPublic' does not have a valid nameAlg
63 // TPM_RC_INSUFFICIENT 'inSymSeed' is nonempty and failed to retrieve ECC
64 // point from the secret; or unmarshaling sensitive value
65 // from 'duplicate' failed the result of 'inSymSeed'
66 // decryption
67 // TPM_RC_INTEGRITY 'duplicate' integrity is broken
68 // TPM_RC_KDF 'objectPublic' representing decrypting keyed hash
69 // object specifies invalid KDF
70 // TPM_RC_KEY inconsistent parameters of 'objectPublic'; or
71 // 'inSymSeed' is nonempty and 'parentHandle' does not
72 // reference a key of supported type; or
73 // invalid key size in 'objectPublic' representing an
74 // asymmetric key
75 // TPM_RC_NO_RESULT 'inSymSeed' is nonempty and multiplication resulted in
76 // ECC point at infinity
77 // TPM_RC_OBJECT_MEMORY no available object slot
78 // TPM_RC_SCHEME inconsistent attributes 'decrypt', 'sign',
79 // 'restricted' and key's scheme ID in 'objectPublic';
80 // or hash algorithm is inconsistent with the scheme ID
81 // for keyed hash object
82 // TPM_RC_SIZE 'authPolicy' size does not match digest size of the
83 // name algorithm in 'objectPublic'; or
84 // 'symmetricAlg' and 'encryptionKey' have different
85 // sizes; or
86 // 'inSymSeed' is nonempty and it size is not
87 // consistent with the type of 'parentHandle'; or
88 // unmarshaling sensitive value from 'duplicate' failed
89 // TPM_RC_SYMMETRIC 'objectPublic' is either a storage key with no
90 // symmetric algorithm or a non-storage key with
91 // symmetric algorithm different from TPM_ALG_NULL
92 // TPM_RC_TYPE unsupported type of 'objectPublic'; or
93 // 'parentHandle' is not a storage key; or
94 // only the public portion of 'parentHandle' is loaded;
95 // or 'objectPublic' and 'duplicate' are of different
96 // types
97 // TPM_RC_VALUE nonempty 'inSymSeed' and its numeric value is
98 // greater than the modulus of the key referenced by
99 // 'parentHandle' or 'inSymSeed' is larger than the
100 // size of the digest produced by the name algorithm of
101 // the symmetric key referenced by 'parentHandle'
102 TPM_RC
TPM2_Import(Import_In * in,Import_Out * out)103 TPM2_Import(
104 Import_In *in, // IN: input parameter list
105 Import_Out *out // OUT: output parameter list
106 )
107 {
108 TPM_RC result = TPM_RC_SUCCESS;
109 OBJECT *parentObject;
110 TPM2B_DATA data; // symmetric key
111 TPMT_SENSITIVE sensitive;
112 TPM2B_NAME name;
113 TPMA_OBJECT attributes;
114 UINT16 innerKeySize = 0; // encrypt key size for inner
115 // wrapper
116
117 // Input Validation
118 // to save typing
119 attributes = in->objectPublic.publicArea.objectAttributes;
120 // FixedTPM and fixedParent must be CLEAR
121 if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)
122 || IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent))
123 return TPM_RCS_ATTRIBUTES + RC_Import_objectPublic;
124
125 // Get parent pointer
126 parentObject = HandleToObject(in->parentHandle);
127
128 if(!ObjectIsParent(parentObject))
129 return TPM_RCS_TYPE + RC_Import_parentHandle;
130
131 if(in->symmetricAlg.algorithm != TPM_ALG_NULL)
132 {
133 // Get inner wrap key size
134 innerKeySize = in->symmetricAlg.keyBits.sym;
135 // Input symmetric key must match the size of algorithm.
136 if(in->encryptionKey.t.size != (innerKeySize + 7) / 8)
137 return TPM_RCS_SIZE + RC_Import_encryptionKey;
138 }
139 else
140 {
141 // If input symmetric algorithm is NULL, input symmetric key size must
142 // be 0 as well
143 if(in->encryptionKey.t.size != 0)
144 return TPM_RCS_SIZE + RC_Import_encryptionKey;
145 // If encryptedDuplication is SET, then the object must have an inner
146 // wrapper
147 if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
148 return TPM_RCS_ATTRIBUTES + RC_Import_encryptionKey;
149 }
150 // See if there is an outer wrapper
151 if(in->inSymSeed.t.size != 0)
152 {
153 // in->inParentHandle is a parent, but in order to decrypt an outer wrapper,
154 // it must be able to do key exchange and a symmetric key can't do that.
155 if(parentObject->publicArea.type == TPM_ALG_SYMCIPHER)
156 return TPM_RCS_TYPE + RC_Import_parentHandle;
157
158 // Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES,
159 // TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT,
160 // TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point
161 result = CryptSecretDecrypt(parentObject, NULL, DUPLICATE_STRING,
162 &in->inSymSeed, &data);
163 pAssert(result != TPM_RC_BINDING);
164 if(result != TPM_RC_SUCCESS)
165 return RcSafeAddToResult(result, RC_Import_inSymSeed);
166 }
167 else
168 {
169 // If encrytpedDuplication is set, then the object must have an outer
170 // wrapper
171 if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
172 return TPM_RCS_ATTRIBUTES + RC_Import_inSymSeed;
173 data.t.size = 0;
174 }
175 // Compute name of object
176 PublicMarshalAndComputeName(&(in->objectPublic.publicArea), &name);
177 if(name.t.size == 0)
178 return TPM_RCS_HASH + RC_Import_objectPublic;
179
180 // Retrieve sensitive from private.
181 // TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here.
182 result = DuplicateToSensitive(&in->duplicate.b, &name.b, parentObject,
183 in->objectPublic.publicArea.nameAlg,
184 &data.b, &in->symmetricAlg,
185 &in->encryptionKey.b, &sensitive);
186 if(result != TPM_RC_SUCCESS)
187 return RcSafeAddToResult(result, RC_Import_duplicate);
188
189 // If the parent of this object has fixedTPM SET, then validate this
190 // object as if it were being loaded so that validation can be skipped
191 // when it is actually loaded.
192 if(IS_ATTRIBUTE(parentObject->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM))
193 {
194 result = ObjectLoad(NULL, NULL, &in->objectPublic.publicArea,
195 &sensitive, RC_Import_objectPublic, RC_Import_duplicate,
196 NULL);
197 }
198 // Command output
199 if(result == TPM_RC_SUCCESS)
200 {
201 // Prepare output private data from sensitive
202 SensitiveToPrivate(&sensitive, &name, parentObject,
203 in->objectPublic.publicArea.nameAlg,
204 &out->outPrivate);
205 }
206 return result;
207 }
208
209 #endif // CC_Import