• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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