• 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 //** Includes
36 #include "Tpm.h"
37 #include "Object_spt_fp.h"
38 
39 //** Local Functions
40 
41 //*** GetIV2BSize()
42 // Get the size of TPM2B_IV in canonical form that will be append to the start of
43 // the sensitive data.  It includes both size of size field and size of iv data
44 static UINT16
GetIV2BSize(OBJECT * protector)45 GetIV2BSize(
46     OBJECT              *protector          // IN: the protector handle
47     )
48 {
49     TPM_ALG_ID          symAlg;
50     UINT16              keyBits;
51 
52     // Determine the symmetric algorithm and size of key
53     if(protector == NULL)
54     {
55         // Use the context encryption algorithm and key size
56         symAlg = CONTEXT_ENCRYPT_ALG;
57         keyBits = CONTEXT_ENCRYPT_KEY_BITS;
58     }
59     else
60     {
61         symAlg = protector->publicArea.parameters.asymDetail.symmetric.algorithm;
62         keyBits = protector->publicArea.parameters.asymDetail.symmetric.keyBits.sym;
63     }
64 
65     // The IV size is a UINT16 size field plus the block size of the symmetric
66     // algorithm
67     return sizeof(UINT16) + CryptGetSymmetricBlockSize(symAlg, keyBits);
68 }
69 
70 //*** ComputeProtectionKeyParms()
71 // This function retrieves the symmetric protection key parameters for
72 // the sensitive data
73 // The parameters retrieved from this function include encryption algorithm,
74 // key size in bit, and a TPM2B_SYM_KEY containing the key material as well as
75 // the key size in bytes
76 // This function is used for any action that requires encrypting or decrypting of
77 // the sensitive area of an object or a credential blob
78 //
79 /*(See part 1 specification)
80     KDF for generating the protection key material:
81     KDFa(hashAlg, seed, "STORAGE", Name, NULL , bits)
82 where
83     hashAlg     for a Primary Object, an algorithm chosen by the TPM vendor
84                 for derivations from Primary Seeds. For all other objects,
85                 the nameAlg of the object's parent.
86     seed        for a Primary Object in the Platform Hierarchy, the PPS.
87                 For Primary Objects in either Storage or Endorsement Hierarchy,
88                 the SPS. For Temporary Objects, the context encryption seed.
89                 For all other objects, the symmetric seed value in the
90                 sensitive area of the object's parent.
91     STORAGE     label to differentiate use of KDFa() (see 4.7)
92     Name        the Name of the object being encrypted
93     bits        the number of bits required for a  symmetric key and IV
94 */
95 //  Return Type: void
96 static void
ComputeProtectionKeyParms(OBJECT * protector,TPM_ALG_ID hashAlg,TPM2B * name,TPM2B * seedIn,TPM_ALG_ID * symAlg,UINT16 * keyBits,TPM2B_SYM_KEY * symKey)97 ComputeProtectionKeyParms(
98     OBJECT          *protector,         // IN: the protector object
99     TPM_ALG_ID       hashAlg,           // IN: hash algorithm for KDFa
100     TPM2B           *name,              // IN: name of the object
101     TPM2B           *seedIn,            // IN: optional seed for duplication blob.
102                                         //     For non duplication blob, this
103                                         //     parameter should be NULL
104     TPM_ALG_ID      *symAlg,            // OUT: the symmetric algorithm
105     UINT16          *keyBits,           // OUT: the symmetric key size in bits
106     TPM2B_SYM_KEY   *symKey             // OUT: the symmetric key
107     )
108 {
109     const TPM2B         *seed = seedIn;
110 
111     // Determine the algorithms for the KDF and the encryption/decryption
112     // For TPM_RH_NULL, using context settings
113     if(protector == NULL)
114     {
115         // Use the context encryption algorithm and key size
116         *symAlg = CONTEXT_ENCRYPT_ALG;
117         symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES;
118         *keyBits = CONTEXT_ENCRYPT_KEY_BITS;
119     }
120     else
121     {
122         TPMT_SYM_DEF_OBJECT *symDef;
123         symDef = &protector->publicArea.parameters.asymDetail.symmetric;
124         *symAlg = symDef->algorithm;
125         *keyBits = symDef->keyBits.sym;
126         symKey->t.size = (*keyBits + 7) / 8;
127     }
128     // Get seed for KDF
129     if(seed == NULL)
130         seed = GetSeedForKDF(protector);
131     // KDFa to generate symmetric key and IV value
132     CryptKDFa(hashAlg, seed, STORAGE_KEY, name, NULL,
133               symKey->t.size * 8, symKey->t.buffer, NULL, FALSE);
134     return;
135 }
136 
137 //*** ComputeOuterIntegrity()
138 // The sensitive area parameter is a buffer that holds a space for
139 // the integrity value and the marshaled sensitive area. The caller should
140 // skip over the area set aside for the integrity value
141 // and compute the hash of the remainder of the object.
142 // The size field of sensitive is in unmarshaled form and the
143 // sensitive area contents is an array of bytes.
144 /*(See part 1 specification)
145     KDFa(hashAlg, seed, "INTEGRITY", NULL, NULL , bits)   (38)
146 where
147     hashAlg     for a Primary Object, the nameAlg of the object. For all other
148                 objects the nameAlg of the object's parent.
149     seed        for a Primary Object in the Platform Hierarchy, the PPS. For
150                 Primary Objects in either Storage or Endorsement Hierarchy,
151                 the SPS. For a Temporary Object, the context encryption key.
152                 For all other objects, the symmetric seed value in the sensitive
153                 area of the object's parent.
154     "INTEGRITY" a value used to differentiate the uses of the KDF.
155     bits        the number of bits in the digest produced by hashAlg.
156 Key is then used in the integrity computation.
157     HMACnameAlg(HMACkey, encSensitive || Name )
158 where
159     HMACnameAlg()   the HMAC function using nameAlg of the object's parent
160     HMACkey         value derived from the parent symmetric protection value
161     encSensitive    symmetrically encrypted sensitive area
162     Name            the Name of the object being protected
163 */
164 //  Return Type: void
165 static void
ComputeOuterIntegrity(TPM2B * name,OBJECT * protector,TPMI_ALG_HASH hashAlg,TPM2B * seedIn,UINT32 sensitiveSize,BYTE * sensitiveData,TPM2B_DIGEST * integrity)166 ComputeOuterIntegrity(
167     TPM2B           *name,              // IN: the name of the object
168     OBJECT          *protector,         // IN: the object that
169                                         //     provides protection. For an object,
170                                         //     it is a parent. For a credential, it
171                                         //     is the encrypt object. For
172                                         //     a Temporary Object, it is NULL
173     TPMI_ALG_HASH    hashAlg,           // IN: algorithm to use for integrity
174     TPM2B           *seedIn,            // IN: an external seed may be provided for
175                                         //     duplication blob. For non duplication
176                                         //     blob, this parameter should be NULL
177     UINT32           sensitiveSize,     // IN: size of the marshaled sensitive data
178     BYTE            *sensitiveData,     // IN: sensitive area
179     TPM2B_DIGEST    *integrity          // OUT: integrity
180     )
181 {
182     HMAC_STATE       hmacState;
183     TPM2B_DIGEST     hmacKey;
184     const TPM2B     *seed = seedIn;
185 //
186     // Get seed for KDF
187     if(seed == NULL)
188         seed = GetSeedForKDF(protector);
189     // Determine the HMAC key bits
190     hmacKey.t.size = CryptHashGetDigestSize(hashAlg);
191 
192     // KDFa to generate HMAC key
193     CryptKDFa(hashAlg, seed, INTEGRITY_KEY, NULL, NULL,
194               hmacKey.t.size * 8, hmacKey.t.buffer, NULL, FALSE);
195     // Start HMAC and get the size of the digest which will become the integrity
196     integrity->t.size = CryptHmacStart2B(&hmacState, hashAlg, &hmacKey.b);
197 
198     // Adding the marshaled sensitive area to the integrity value
199     CryptDigestUpdate(&hmacState.hashState, sensitiveSize, sensitiveData);
200 
201     // Adding name
202     CryptDigestUpdate2B(&hmacState.hashState, name);
203 
204     // Compute HMAC
205     CryptHmacEnd2B(&hmacState, &integrity->b);
206 
207     return;
208 }
209 
210 //*** ComputeInnerIntegrity()
211 // This function computes the integrity of an inner wrap
212 static void
ComputeInnerIntegrity(TPM_ALG_ID hashAlg,TPM2B * name,UINT16 dataSize,BYTE * sensitiveData,TPM2B_DIGEST * integrity)213 ComputeInnerIntegrity(
214     TPM_ALG_ID       hashAlg,       // IN: hash algorithm for inner wrap
215     TPM2B           *name,          // IN: the name of the object
216     UINT16           dataSize,      // IN: the size of sensitive data
217     BYTE            *sensitiveData, // IN: sensitive data
218     TPM2B_DIGEST    *integrity      // OUT: inner integrity
219     )
220 {
221     HASH_STATE      hashState;
222 //
223     // Start hash and get the size of the digest which will become the integrity
224     integrity->t.size = CryptHashStart(&hashState, hashAlg);
225 
226     // Adding the marshaled sensitive area to the integrity value
227     CryptDigestUpdate(&hashState, dataSize, sensitiveData);
228 
229     // Adding name
230     CryptDigestUpdate2B(&hashState, name);
231 
232     // Compute hash
233     CryptHashEnd2B(&hashState, &integrity->b);
234 
235     return;
236 }
237 
238 //*** ProduceInnerIntegrity()
239 // This function produces an inner integrity for regular private, credential or
240 // duplication blob
241 // It requires the sensitive data being marshaled to the innerBuffer, with the
242 // leading bytes reserved for integrity hash.  It assume the sensitive data
243 // starts at address (innerBuffer + integrity size).
244 // This function integrity at the beginning of the inner buffer
245 // It returns the total size of buffer with the inner wrap
246 static UINT16
ProduceInnerIntegrity(TPM2B * name,TPM_ALG_ID hashAlg,UINT16 dataSize,BYTE * innerBuffer)247 ProduceInnerIntegrity(
248     TPM2B           *name,          // IN: the name of the object
249     TPM_ALG_ID       hashAlg,       // IN: hash algorithm for inner wrap
250     UINT16           dataSize,      // IN: the size of sensitive data, excluding the
251                                     //     leading integrity buffer size
252     BYTE            *innerBuffer    // IN/OUT: inner buffer with sensitive data in
253                                     //     it.  At input, the leading bytes of this
254                                     //     buffer is reserved for integrity
255     )
256 {
257     BYTE            *sensitiveData; // pointer to the sensitive data
258     TPM2B_DIGEST     integrity;
259     UINT16           integritySize;
260     BYTE            *buffer;        // Auxiliary buffer pointer
261 //
262     // sensitiveData points to the beginning of sensitive data in innerBuffer
263     integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg);
264     sensitiveData = innerBuffer + integritySize;
265 
266     ComputeInnerIntegrity(hashAlg, name, dataSize, sensitiveData, &integrity);
267 
268     // Add integrity at the beginning of inner buffer
269     buffer = innerBuffer;
270     TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL);
271 
272     return dataSize + integritySize;
273 }
274 
275 //*** CheckInnerIntegrity()
276 // This function check integrity of inner blob
277 //  Return Type: TPM_RC
278 //      TPM_RC_INTEGRITY        if the outer blob integrity is bad
279 //      unmarshal errors        unmarshal errors while unmarshaling integrity
280 static TPM_RC
CheckInnerIntegrity(TPM2B * name,TPM_ALG_ID hashAlg,UINT16 dataSize,BYTE * innerBuffer)281 CheckInnerIntegrity(
282     TPM2B           *name,          // IN: the name of the object
283     TPM_ALG_ID       hashAlg,       // IN: hash algorithm for inner wrap
284     UINT16           dataSize,      // IN: the size of sensitive data, including the
285                                     //     leading integrity buffer size
286     BYTE            *innerBuffer    // IN/OUT: inner buffer with sensitive data in
287                                     //     it
288     )
289 {
290     TPM_RC          result;
291     TPM2B_DIGEST    integrity;
292     TPM2B_DIGEST    integrityToCompare;
293     BYTE            *buffer;                // Auxiliary buffer pointer
294     INT32           size;
295 //
296     // Unmarshal integrity
297     buffer = innerBuffer;
298     size = (INT32)dataSize;
299     result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);
300     if(result == TPM_RC_SUCCESS)
301     {
302         // Compute integrity to compare
303         ComputeInnerIntegrity(hashAlg, name, (UINT16)size, buffer,
304                               &integrityToCompare);
305         // Compare outer blob integrity
306         if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b))
307             result = TPM_RC_INTEGRITY;
308     }
309     return result;
310 }
311 
312 //** Public Functions
313 
314 //*** AdjustAuthSize()
315 // This function will validate that the input authValue is no larger than the
316 // digestSize for the nameAlg. It will then pad with zeros to the size of the
317 // digest.
318 BOOL
AdjustAuthSize(TPM2B_AUTH * auth,TPMI_ALG_HASH nameAlg)319 AdjustAuthSize(
320     TPM2B_AUTH          *auth,          // IN/OUT: value to adjust
321     TPMI_ALG_HASH        nameAlg        // IN:
322     )
323 {
324     UINT16               digestSize;
325 //
326     // If there is no nameAlg, then this is a LoadExternal and the authVale can
327     // be any size up to the maximum allowed by the implementation
328     digestSize = (nameAlg == TPM_ALG_NULL) ? sizeof(TPMU_HA)
329         : CryptHashGetDigestSize(nameAlg);
330     if(digestSize < MemoryRemoveTrailingZeros(auth))
331         return FALSE;
332     else if(digestSize > auth->t.size)
333         MemoryPad2B(&auth->b, digestSize);
334     auth->t.size = digestSize;
335 
336     return TRUE;
337 }
338 
339 //*** AreAttributesForParent()
340 // This function is called by create, load, and import functions.
341 //
342 // Note: The 'isParent' attribute is SET when an object is loaded and it has
343 // attributes that are suitable for a parent object.
344 //  Return Type: BOOL
345 //      TRUE(1)         properties are those of a parent
346 //      FALSE(0)        properties are not those of a parent
347 BOOL
ObjectIsParent(OBJECT * parentObject)348 ObjectIsParent(
349     OBJECT          *parentObject   // IN: parent handle
350     )
351 {
352     return parentObject->attributes.isParent;
353 }
354 
355 //*** CreateChecks()
356 // Attribute checks that are unique to creation.
357 //  Return Type: TPM_RC
358 //      TPM_RC_ATTRIBUTES   sensitiveDataOrigin is not consistent with the
359 //                          object type
360 //      other               returns from PublicAttributesValidation()
361 TPM_RC
CreateChecks(OBJECT * parentObject,TPMT_PUBLIC * publicArea,UINT16 sensitiveDataSize)362 CreateChecks(
363     OBJECT              *parentObject,
364     TPMT_PUBLIC         *publicArea,
365     UINT16               sensitiveDataSize
366     )
367 {
368     TPMA_OBJECT          attributes = publicArea->objectAttributes;
369     TPM_RC               result = TPM_RC_SUCCESS;
370 //
371     // If the caller indicates that they have provided the data, then make sure that
372     // they have provided some data.
373     if((!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
374        && (sensitiveDataSize == 0))
375         return TPM_RCS_ATTRIBUTES;
376     // For an ordinary object, data can only be provided when sensitiveDataOrigin
377     // is CLEAR
378     if((parentObject != NULL)
379        && (IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
380        && (sensitiveDataSize != 0))
381         return TPM_RCS_ATTRIBUTES;
382     switch(publicArea->type)
383     {
384         case TPM_ALG_KEYEDHASH:
385             // if this is a data object (sign == decrypt == CLEAR) then the
386             // TPM cannot be the data source.
387             if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)
388                && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)
389                && IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
390                 result = TPM_RC_ATTRIBUTES;
391             // comment out the next line in order to prevent a fixedTPM derivation
392             // parent
393 //            break;
394         case TPM_ALG_SYMCIPHER:
395             // A restricted key symmetric key (SYMCIPHER and KEYEDHASH)
396             // must have sensitiveDataOrigin SET unless it has fixedParent and
397             // fixedTPM CLEAR.
398             if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
399                 if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
400                     if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)
401                        || IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
402                         result = TPM_RCS_ATTRIBUTES;
403             break;
404         default: // Asymmetric keys cannot have the sensitive portion provided
405             if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
406                 result = TPM_RCS_ATTRIBUTES;
407             break;
408     }
409     if(TPM_RC_SUCCESS == result)
410     {
411         result = PublicAttributesValidation(parentObject, publicArea);
412     }
413     return result;
414 }
415 //*** SchemeChecks
416 // This function is called by TPM2_LoadExternal() and PublicAttributesValidation().
417 // This function validates the schemes in the public area of an object.
418 //  Return Type: TPM_RC
419 //      TPM_RC_HASH         non-duplicable storage key and its parent have different
420 //                          name algorithm
421 //      TPM_RC_KDF          incorrect KDF specified for decrypting keyed hash object
422 //      TPM_RC_KEY          invalid key size values in an asymmetric key public area
423 //      TPM_RCS_SCHEME       inconsistent attributes 'decrypt', 'sign', 'restricted'
424 //                          and key's scheme ID; or hash algorithm is inconsistent
425 //                          with the scheme ID for keyed hash object
426 //      TPM_RC_SYMMETRIC    a storage key with no symmetric algorithm specified; or
427 //                          non-storage key with symmetric algorithm different from
428 //                          TPM_ALG_NULL
429 TPM_RC
SchemeChecks(OBJECT * parentObject,TPMT_PUBLIC * publicArea)430 SchemeChecks(
431     OBJECT          *parentObject,  // IN: parent (null if primary seed)
432     TPMT_PUBLIC     *publicArea     // IN: public area of the object
433     )
434 {
435     TPMT_SYM_DEF_OBJECT     *symAlgs = NULL;
436     TPM_ALG_ID               scheme = TPM_ALG_NULL;
437     TPMA_OBJECT              attributes = publicArea->objectAttributes;
438     TPMU_PUBLIC_PARMS        *parms = &publicArea->parameters;
439 //
440     switch(publicArea->type)
441     {
442         case TPM_ALG_SYMCIPHER:
443             symAlgs = &parms->symDetail.sym;
444             // If this is a decrypt key, then only the block cipher modes (not
445             // SMAC) are valid. TPM_ALG_NULL is OK too. If this is a 'sign' key,
446             // then any mode that got through the unmarshaling is OK.
447             if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)
448                && !CryptSymModeIsValid(symAlgs->mode.sym, TRUE))
449                 return TPM_RCS_SCHEME;
450             break;
451         case TPM_ALG_KEYEDHASH:
452             scheme = parms->keyedHashDetail.scheme.scheme;
453             // if both sign and decrypt
454             if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)
455                == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
456             {
457                 // if both sign and decrypt are set or clear, then need
458                 // TPM_ALG_NULL as scheme
459                 if(scheme != TPM_ALG_NULL)
460                     return TPM_RCS_SCHEME;
461             }
462             else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)
463                     && scheme != TPM_ALG_HMAC)
464                 return TPM_RCS_SCHEME;
465             else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
466             {
467                 if(scheme != TPM_ALG_XOR)
468                     return TPM_RCS_SCHEME;
469                 // If this is a derivation parent, then the KDF needs to be
470                 // SP800-108 for this implementation. This is the only derivation
471                 // supported by this implementation. Other implementations could
472                 // support additional schemes. There is no default.
473                 if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
474                 {
475                     if(parms->keyedHashDetail.scheme.details.xor.kdf
476                        != TPM_ALG_KDF1_SP800_108)
477                         return TPM_RCS_SCHEME;
478                     // Must select a digest.
479                     if(CryptHashGetDigestSize(
480                         parms->keyedHashDetail.scheme.details.xor.hashAlg) == 0)
481                         return TPM_RCS_HASH;
482                 }
483             }
484             break;
485         default: // handling for asymmetric
486             scheme = parms->asymDetail.scheme.scheme;
487             symAlgs = &parms->asymDetail.symmetric;
488             // if the key is both sign and decrypt, then the scheme must be
489             // TPM_ALG_NULL because there is no way to specify both a sign and a
490             // decrypt scheme in the key.
491             if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)
492                == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
493             {
494                 // scheme must be TPM_ALG_NULL
495                 if(scheme != TPM_ALG_NULL)
496                     return TPM_RCS_SCHEME;
497             }
498             else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign))
499             {
500                 // If this is a signing key, see if it has a signing scheme
501                 if(CryptIsAsymSignScheme(publicArea->type, scheme))
502                 {
503                     // if proper signing scheme then it needs a proper hash
504                     if(parms->asymDetail.scheme.details.anySig.hashAlg
505                        == TPM_ALG_NULL)
506                         return TPM_RCS_SCHEME;
507                 }
508                 else
509                 {
510                     // signing key that does not have a proper signing scheme.
511                     // This is OK if the key is not restricted and its scheme
512                     // is TPM_ALG_NULL
513                     if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)
514                        || scheme != TPM_ALG_NULL)
515                         return TPM_RCS_SCHEME;
516                 }
517             }
518             else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
519             {
520                 if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
521                 {
522                     // for a restricted decryption key (a parent), scheme
523                     // is required to be TPM_ALG_NULL
524                     if(scheme != TPM_ALG_NULL)
525                         return TPM_RCS_SCHEME;
526                 }
527                 else
528                 {
529                     // For an unrestricted decryption key, the scheme has to
530                     // be a valid scheme or TPM_ALG_NULL
531                     if(scheme != TPM_ALG_NULL &&
532                        !CryptIsAsymDecryptScheme(publicArea->type, scheme))
533                         return TPM_RCS_SCHEME;
534                 }
535             }
536             if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)
537                || !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
538             {
539                 // For an asymmetric key that is not a parent, the symmetric
540                 // algorithms must be TPM_ALG_NULL
541                 if(symAlgs->algorithm != TPM_ALG_NULL)
542                     return TPM_RCS_SYMMETRIC;
543             }
544             // Special checks for an ECC key
545 #if ALG_ECC
546             if(publicArea->type == TPM_ALG_ECC)
547             {
548                 TPM_ECC_CURVE            curveID;
549                 const TPMT_ECC_SCHEME   *curveScheme;
550 
551                 curveID = publicArea->parameters.eccDetail.curveID;
552                 curveScheme = CryptGetCurveSignScheme(curveID);
553                 // The curveId must be valid or the unmarshaling is busted.
554                 pAssert(curveScheme != NULL);
555 
556                 // If the curveID requires a specific scheme, then the key must
557                 // select the same scheme
558                 if(curveScheme->scheme != TPM_ALG_NULL)
559                 {
560                     TPMS_ECC_PARMS      *ecc = &publicArea->parameters.eccDetail;
561                     if(scheme != curveScheme->scheme)
562                         return TPM_RCS_SCHEME;
563                     // The scheme can allow any hash, or not...
564                     if(curveScheme->details.anySig.hashAlg != TPM_ALG_NULL
565                        && (ecc->scheme.details.anySig.hashAlg
566                            != curveScheme->details.anySig.hashAlg))
567                         return TPM_RCS_SCHEME;
568                 }
569                 // For now, the KDF must be TPM_ALG_NULL
570                 if(publicArea->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL)
571                     return TPM_RCS_KDF;
572             }
573 #endif
574             break;
575     }
576     // If this is a restricted decryption key with symmetric algorithms, then it
577     // is an ordinary parent (not a derivation parent). It needs to specific
578     // symmetric algorithms other than TPM_ALG_NULL
579     if(symAlgs != NULL
580        && IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)
581        && IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
582     {
583         if(symAlgs->algorithm == TPM_ALG_NULL)
584             return TPM_RCS_SYMMETRIC;
585 #if 0       //??
586 // This next check is under investigation. Need to see if it will break Windows
587 // before it is enabled. If it does not, then it should be default because a
588 // the mode used with a parent is always CFB and Part 2 indicates as much.
589         if(symAlgs->mode.sym != TPM_ALG_CFB)
590             return TPM_RCS_MODE;
591 #endif
592         // If this parent is not duplicable, then the symmetric algorithms
593         // (encryption and hash) must match those of its parent
594         if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)
595            && (parentObject != NULL))
596         {
597             if(publicArea->nameAlg != parentObject->publicArea.nameAlg)
598                 return TPM_RCS_HASH;
599             if(!MemoryEqual(symAlgs, &parentObject->publicArea.parameters,
600                             sizeof(TPMT_SYM_DEF_OBJECT)))
601                 return TPM_RCS_SYMMETRIC;
602         }
603     }
604     return TPM_RC_SUCCESS;
605 }
606 
607 //*** PublicAttributesValidation()
608 // This function validates the values in the public area of an object.
609 // This function is used in the processing of TPM2_Create, TPM2_CreatePrimary,
610 // TPM2_CreateLoaded(), TPM2_Load(),  TPM2_Import(), and TPM2_LoadExternal().
611 // For TPM2_Import() this is only used if the new parent has fixedTPM SET. For
612 // TPM2_LoadExternal(), this is not used for a public-only key
613 //  Return Type: TPM_RC
614 //      TPM_RC_ATTRIBUTES   'fixedTPM', 'fixedParent', or 'encryptedDuplication'
615 //                          attributes are inconsistent between themselves or with
616 //                          those of the parent object;
617 //                          inconsistent 'restricted', 'decrypt' and 'sign'
618 //                          attributes;
619 //                          attempt to inject sensitive data for an asymmetric key;
620 //                          attempt to create a symmetric cipher key that is not
621 //                          a decryption key
622 //      TPM_RC_HASH         nameAlg is TPM_ALG_NULL
623 //      TPM_RC_SIZE         'authPolicy' size does not match digest size of the name
624 //                          algorithm in 'publicArea'
625 //   other                  returns from SchemeChecks()
626 TPM_RC
PublicAttributesValidation(OBJECT * parentObject,TPMT_PUBLIC * publicArea)627 PublicAttributesValidation(
628     OBJECT          *parentObject,  // IN: input parent object
629     TPMT_PUBLIC     *publicArea     // IN: public area of the object
630     )
631 {
632     TPMA_OBJECT      attributes = publicArea->objectAttributes;
633     TPMA_OBJECT      parentAttributes = TPMA_ZERO_INITIALIZER();
634 //
635     if(parentObject != NULL)
636         parentAttributes = parentObject->publicArea.objectAttributes;
637     if(publicArea->nameAlg == TPM_ALG_NULL)
638         return TPM_RCS_HASH;
639     // If there is an authPolicy, it needs to be the size of the digest produced
640     // by the nameAlg of the object
641     if((publicArea->authPolicy.t.size != 0
642         && (publicArea->authPolicy.t.size
643             != CryptHashGetDigestSize(publicArea->nameAlg))))
644         return TPM_RCS_SIZE;
645     // If the parent is fixedTPM (including a Primary Object) the object must have
646     // the same value for fixedTPM and fixedParent
647     if(parentObject == NULL
648        || IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM))
649     {
650         if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)
651            != IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
652             return TPM_RCS_ATTRIBUTES;
653     }
654     else
655     {
656         // The parent is not fixedTPM so the object can't be fixedTPM
657         if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
658             return  TPM_RCS_ATTRIBUTES;
659     }
660     // See if sign and decrypt are the same
661     if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)
662        == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
663     {
664         // a restricted key cannot have both SET or both CLEAR
665         if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
666             return TPM_RC_ATTRIBUTES;
667         // only a data object may have both sign and decrypt CLEAR
668         // BTW, since we know that decrypt==sign, no need to check both
669         if(publicArea->type != TPM_ALG_KEYEDHASH
670            && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign))
671             return TPM_RC_ATTRIBUTES;
672     }
673     // If the object can't be duplicated (directly or indirectly) then there
674     // is no justification for having encryptedDuplication SET
675     if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)
676        && IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
677         return TPM_RCS_ATTRIBUTES;
678     // If a parent object has fixedTPM CLEAR, the child must have the
679     // same encryptedDuplication value as its parent.
680     // Primary objects are considered to have a fixedTPM parent (the seeds).
681     if(parentObject != NULL
682        && !IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM))
683     {
684         if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)
685            != IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, encryptedDuplication))
686             return TPM_RCS_ATTRIBUTES;
687     }
688     // Special checks for derived objects
689     if((parentObject != NULL) && (parentObject->attributes.derivation == SET))
690     {
691         // A derived object has the same settings for fixedTPM as its parent
692         if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)
693            != IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM))
694             return TPM_RCS_ATTRIBUTES;
695         // A derived object is required to be fixedParent
696         if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent))
697             return TPM_RCS_ATTRIBUTES;
698     }
699     return SchemeChecks(parentObject, publicArea);
700 }
701 
702 //*** FillInCreationData()
703 // Fill in creation data for an object.
704 //  Return Type: void
705 void
FillInCreationData(TPMI_DH_OBJECT parentHandle,TPMI_ALG_HASH nameHashAlg,TPML_PCR_SELECTION * creationPCR,TPM2B_DATA * outsideData,TPM2B_CREATION_DATA * outCreation,TPM2B_DIGEST * creationDigest)706 FillInCreationData(
707     TPMI_DH_OBJECT           parentHandle,  // IN: handle of parent
708     TPMI_ALG_HASH            nameHashAlg,   // IN: name hash algorithm
709     TPML_PCR_SELECTION      *creationPCR,   // IN: PCR selection
710     TPM2B_DATA              *outsideData,   // IN: outside data
711     TPM2B_CREATION_DATA     *outCreation,   // OUT: creation data for output
712     TPM2B_DIGEST            *creationDigest // OUT: creation digest
713     )
714 {
715     BYTE                 creationBuffer[sizeof(TPMS_CREATION_DATA)];
716     BYTE                *buffer;
717     HASH_STATE           hashState;
718 //
719     // Fill in TPMS_CREATION_DATA in outCreation
720 
721     // Compute PCR digest
722     PCRComputeCurrentDigest(nameHashAlg, creationPCR,
723                             &outCreation->creationData.pcrDigest);
724 
725     // Put back PCR selection list
726     outCreation->creationData.pcrSelect = *creationPCR;
727 
728     // Get locality
729     outCreation->creationData.locality
730         = LocalityGetAttributes(_plat__LocalityGet());
731     outCreation->creationData.parentNameAlg = TPM_ALG_NULL;
732 
733     // If the parent is either a primary seed or TPM_ALG_NULL, then  the Name
734     // and QN of the parent are the parent's handle.
735     if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)
736     {
737         buffer = &outCreation->creationData.parentName.t.name[0];
738         outCreation->creationData.parentName.t.size =
739             TPM_HANDLE_Marshal(&parentHandle, &buffer, NULL);
740         // For a primary or temporary object, the parent name (a handle) and the
741         // parent's QN are the same
742         outCreation->creationData.parentQualifiedName
743             = outCreation->creationData.parentName;
744     }
745     else         // Regular object
746     {
747         OBJECT          *parentObject = HandleToObject(parentHandle);
748 //
749         // Set name algorithm
750         outCreation->creationData.parentNameAlg = parentObject->publicArea.nameAlg;
751 
752         // Copy parent name
753         outCreation->creationData.parentName = parentObject->name;
754 
755         // Copy parent qualified name
756         outCreation->creationData.parentQualifiedName = parentObject->qualifiedName;
757     }
758     // Copy outside information
759     outCreation->creationData.outsideInfo = *outsideData;
760 
761     // Marshal creation data to canonical form
762     buffer = creationBuffer;
763     outCreation->size = TPMS_CREATION_DATA_Marshal(&outCreation->creationData,
764                                                    &buffer, NULL);
765     // Compute hash for creation field in public template
766     creationDigest->t.size = CryptHashStart(&hashState, nameHashAlg);
767     CryptDigestUpdate(&hashState, outCreation->size, creationBuffer);
768     CryptHashEnd2B(&hashState, &creationDigest->b);
769 
770     return;
771 }
772 
773 //*** GetSeedForKDF()
774 // Get a seed for KDF.  The KDF for encryption and HMAC key use the same seed.
775 const TPM2B *
GetSeedForKDF(OBJECT * protector)776 GetSeedForKDF(
777     OBJECT          *protector         // IN: the protector handle
778     )
779 {
780     // Get seed for encryption key.  Use input seed if provided.
781     // Otherwise, using protector object's seedValue.  TPM_RH_NULL is the only
782     // exception that we may not have a loaded object as protector.  In such a
783     // case, use nullProof as seed.
784     if(protector == NULL)
785         return &gr.nullProof.b;
786     else
787         return &protector->sensitive.seedValue.b;
788 }
789 
790 //*** ProduceOuterWrap()
791 // This function produce outer wrap for a buffer containing the sensitive data.
792 // It requires the sensitive data being marshaled to the outerBuffer, with the
793 // leading bytes reserved for integrity hash.  If iv is used, iv space should
794 // be reserved at the beginning of the buffer.  It assumes the sensitive data
795 // starts at address (outerBuffer + integrity size [+ iv size]).
796 // This function performs:
797 //  1. Add IV before sensitive area if required
798 //  2. encrypt sensitive data, if iv is required, encrypt by iv.  otherwise,
799 //     encrypted by a NULL iv
800 //  3. add HMAC integrity at the beginning of the buffer
801 // It returns the total size of blob with outer wrap
802 UINT16
ProduceOuterWrap(OBJECT * protector,TPM2B * name,TPM_ALG_ID hashAlg,TPM2B * seed,BOOL useIV,UINT16 dataSize,BYTE * outerBuffer)803 ProduceOuterWrap(
804     OBJECT          *protector,     // IN: The handle of the object that provides
805                                     //     protection.  For object, it is parent
806                                     //     handle. For credential, it is the handle
807                                     //     of encrypt object.
808     TPM2B           *name,          // IN: the name of the object
809     TPM_ALG_ID       hashAlg,       // IN: hash algorithm for outer wrap
810     TPM2B           *seed,          // IN: an external seed may be provided for
811                                     //     duplication blob. For non duplication
812                                     //     blob, this parameter should be NULL
813     BOOL             useIV,         // IN: indicate if an IV is used
814     UINT16           dataSize,      // IN: the size of sensitive data, excluding the
815                                     //     leading integrity buffer size or the
816                                     //     optional iv size
817     BYTE            *outerBuffer    // IN/OUT: outer buffer with sensitive data in
818                                     //     it
819     )
820 {
821     TPM_ALG_ID      symAlg;
822     UINT16          keyBits;
823     TPM2B_SYM_KEY   symKey;
824     TPM2B_IV        ivRNG;          // IV from RNG
825     TPM2B_IV        *iv = NULL;
826     UINT16          ivSize = 0;     // size of iv area, including the size field
827     BYTE            *sensitiveData; // pointer to the sensitive data
828     TPM2B_DIGEST    integrity;
829     UINT16          integritySize;
830     BYTE            *buffer;        // Auxiliary buffer pointer
831 //
832     // Compute the beginning of sensitive data.  The outer integrity should
833     // always exist if this function is called to make an outer wrap
834     integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg);
835     sensitiveData = outerBuffer + integritySize;
836 
837     // If iv is used, adjust the pointer of sensitive data and add iv before it
838     if(useIV)
839     {
840         ivSize = GetIV2BSize(protector);
841 
842         // Generate IV from RNG.  The iv data size should be the total IV area
843         // size minus the size of size field
844         ivRNG.t.size = ivSize - sizeof(UINT16);
845         CryptRandomGenerate(ivRNG.t.size, ivRNG.t.buffer);
846 
847         // Marshal IV to buffer
848         buffer = sensitiveData;
849         TPM2B_IV_Marshal(&ivRNG, &buffer, NULL);
850 
851         // adjust sensitive data starting after IV area
852         sensitiveData += ivSize;
853 
854         // Use iv for encryption
855         iv = &ivRNG;
856     }
857     // Compute symmetric key parameters for outer buffer encryption
858     ComputeProtectionKeyParms(protector, hashAlg, name, seed,
859                               &symAlg, &keyBits, &symKey);
860     // Encrypt inner buffer in place
861     CryptSymmetricEncrypt(sensitiveData, symAlg, keyBits,
862                           symKey.t.buffer, iv, TPM_ALG_CFB, dataSize,
863                           sensitiveData);
864     // Compute outer integrity.  Integrity computation includes the optional IV
865     // area
866     ComputeOuterIntegrity(name, protector, hashAlg, seed, dataSize + ivSize,
867                           outerBuffer + integritySize, &integrity);
868     // Add integrity at the beginning of outer buffer
869     buffer = outerBuffer;
870     TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL);
871 
872     // return the total size in outer wrap
873     return dataSize + integritySize + ivSize;
874 }
875 
876 //*** UnwrapOuter()
877 // This function remove the outer wrap of a blob containing sensitive data
878 // This function performs:
879 //  1. check integrity of outer blob
880 //  2. decrypt outer blob
881 //
882 //  Return Type: TPM_RC
883 //      TPM_RCS_INSUFFICIENT     error during sensitive data unmarshaling
884 //      TPM_RCS_INTEGRITY        sensitive data integrity is broken
885 //      TPM_RCS_SIZE             error during sensitive data unmarshaling
886 //      TPM_RCS_VALUE            IV size for CFB does not match the encryption
887 //                               algorithm block size
888 TPM_RC
UnwrapOuter(OBJECT * protector,TPM2B * name,TPM_ALG_ID hashAlg,TPM2B * seed,BOOL useIV,UINT16 dataSize,BYTE * outerBuffer)889 UnwrapOuter(
890     OBJECT          *protector,     // IN: The object that provides
891                                     //     protection.  For object, it is parent
892                                     //     handle. For credential, it is the
893                                     //     encrypt object.
894     TPM2B           *name,          // IN: the name of the object
895     TPM_ALG_ID       hashAlg,       // IN: hash algorithm for outer wrap
896     TPM2B           *seed,          // IN: an external seed may be provided for
897                                     //     duplication blob. For non duplication
898                                     //     blob, this parameter should be NULL.
899     BOOL             useIV,         // IN: indicates if an IV is used
900     UINT16           dataSize,      // IN: size of sensitive data in outerBuffer,
901                                     //     including the leading integrity buffer
902                                     //     size, and an optional iv area
903     BYTE            *outerBuffer    // IN/OUT: sensitive data
904     )
905 {
906     TPM_RC          result;
907     TPM_ALG_ID      symAlg = TPM_ALG_NULL;
908     TPM2B_SYM_KEY   symKey;
909     UINT16          keyBits = 0;
910     TPM2B_IV        ivIn;               // input IV retrieved from input buffer
911     TPM2B_IV        *iv = NULL;
912     BYTE            *sensitiveData;     // pointer to the sensitive data
913     TPM2B_DIGEST    integrityToCompare;
914     TPM2B_DIGEST    integrity;
915     INT32           size;
916 //
917     // Unmarshal integrity
918     sensitiveData = outerBuffer;
919     size = (INT32)dataSize;
920     result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size);
921     if(result == TPM_RC_SUCCESS)
922     {
923         // Compute integrity to compare
924         ComputeOuterIntegrity(name, protector, hashAlg, seed,
925                               (UINT16)size, sensitiveData,
926                               &integrityToCompare);
927         // Compare outer blob integrity
928         if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b))
929             return TPM_RCS_INTEGRITY;
930         // Get the symmetric algorithm parameters used for encryption
931         ComputeProtectionKeyParms(protector, hashAlg, name, seed,
932                                   &symAlg, &keyBits, &symKey);
933         // Retrieve IV if it is used
934         if(useIV)
935         {
936             result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size);
937             if(result == TPM_RC_SUCCESS)
938             {
939                 // The input iv size for CFB must match the encryption algorithm
940                 // block size
941                 if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits))
942                     result = TPM_RC_VALUE;
943                 else
944                     iv = &ivIn;
945             }
946         }
947     }
948     // If no errors, decrypt private in place. Since this function uses CFB,
949     // CryptSymmetricDecrypt() will not return any errors. It may fail but it will
950     // not return an error.
951     if(result == TPM_RC_SUCCESS)
952         CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits,
953                               symKey.t.buffer, iv, TPM_ALG_CFB,
954                               (UINT16)size, sensitiveData);
955     return result;
956 }
957 
958 //*** MarshalSensitive()
959 // This function is used to marshal a sensitive area. Among other things, it
960 // adjusts the size of the authValue to be no smaller than the digest of
961 // 'nameAlg'
962 // Returns the size of the marshaled area.
963 static UINT16
MarshalSensitive(OBJECT * parent,BYTE * buffer,TPMT_SENSITIVE * sensitive,TPMI_ALG_HASH nameAlg)964 MarshalSensitive(
965     OBJECT              *parent,            // IN: the object parent (optional)
966     BYTE                *buffer,            // OUT: receiving buffer
967     TPMT_SENSITIVE      *sensitive,         // IN: the sensitive area to marshal
968     TPMI_ALG_HASH        nameAlg            // IN:
969     )
970 {
971     BYTE                *sizeField = buffer;    // saved so that size can be
972                                                 // marshaled after it is known
973     UINT16               retVal;
974 //
975     // Pad the authValue if needed
976     MemoryPad2B(&sensitive->authValue.b, CryptHashGetDigestSize(nameAlg));
977     buffer += 2;
978 
979     // Marshal the structure
980 #if ALG_RSA
981     // If the sensitive size is the special case for a prime in the type
982     if((sensitive->sensitive.rsa.t.size & RSA_prime_flag) > 0)
983     {
984         UINT16               sizeSave = sensitive->sensitive.rsa.t.size;
985     //
986         // Turn off the flag that indicates that the sensitive->sensitive contains
987         // the CRT form of the exponent.
988         sensitive->sensitive.rsa.t.size &= ~(RSA_prime_flag);
989         // If the parent isn't fixedTPM, then truncate the sensitive data to be
990         // the size of the prime. Otherwise, leave it at the current size which
991         // is the full CRT size.
992         if(parent == NULL
993            || !IS_ATTRIBUTE(parent->publicArea.objectAttributes,
994                             TPMA_OBJECT, fixedTPM))
995             sensitive->sensitive.rsa.t.size /= 5;
996         retVal = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL);
997         // Restore the flag and the size.
998         sensitive->sensitive.rsa.t.size = sizeSave;
999     }
1000     else
1001 #endif
1002     retVal = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL);
1003 
1004     // Marshal the size
1005     retVal = (UINT16)(retVal + UINT16_Marshal(&retVal, &sizeField, NULL));
1006 
1007     return retVal;
1008 }
1009 
1010 //*** SensitiveToPrivate()
1011 // This function prepare the private blob for off the chip storage
1012 // The operations in this function:
1013 //  1. marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE
1014 //  2. apply encryption to the sensitive area.
1015 //  3. apply outer integrity computation.
1016 void
SensitiveToPrivate(TPMT_SENSITIVE * sensitive,TPM2B_NAME * name,OBJECT * parent,TPM_ALG_ID nameAlg,TPM2B_PRIVATE * outPrivate)1017 SensitiveToPrivate(
1018     TPMT_SENSITIVE  *sensitive,     // IN: sensitive structure
1019     TPM2B_NAME      *name,          // IN: the name of the object
1020     OBJECT          *parent,        // IN: The parent object
1021     TPM_ALG_ID       nameAlg,       // IN: hash algorithm in public area.  This
1022                                     //     parameter is used when parentHandle is
1023                                     //     NULL, in which case the object is
1024                                     //     temporary.
1025     TPM2B_PRIVATE   *outPrivate     // OUT: output private structure
1026     )
1027 {
1028     BYTE                *sensitiveData;     // pointer to the sensitive data
1029     UINT16              dataSize;           // data blob size
1030     TPMI_ALG_HASH       hashAlg;            // hash algorithm for integrity
1031     UINT16              integritySize;
1032     UINT16              ivSize;
1033 //
1034     pAssert(name != NULL && name->t.size != 0);
1035 
1036     // Find the hash algorithm for integrity computation
1037     if(parent == NULL)
1038     {
1039         // For Temporary Object, using self name algorithm
1040         hashAlg = nameAlg;
1041     }
1042     else
1043     {
1044         // Otherwise, using parent's name algorithm
1045         hashAlg = parent->publicArea.nameAlg;
1046     }
1047     // Starting of sensitive data without wrappers
1048     sensitiveData = outPrivate->t.buffer;
1049 
1050     // Compute the integrity size
1051     integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg);
1052 
1053     // Reserve space for integrity
1054     sensitiveData += integritySize;
1055 
1056     // Get iv size
1057     ivSize = GetIV2BSize(parent);
1058 
1059     // Reserve space for iv
1060     sensitiveData += ivSize;
1061 
1062     // Marshal the sensitive area including authValue size adjustments.
1063     dataSize = MarshalSensitive(parent, sensitiveData, sensitive, nameAlg);
1064 
1065     //Produce outer wrap, including encryption and HMAC
1066     outPrivate->t.size = ProduceOuterWrap(parent, &name->b, hashAlg, NULL,
1067                                           TRUE, dataSize, outPrivate->t.buffer);
1068     return;
1069 }
1070 
1071 //*** PrivateToSensitive()
1072 // Unwrap an input private area; check the integrity; decrypt and retrieve data
1073 // to a sensitive structure.
1074 // The operations in this function:
1075 //  1. check the integrity HMAC of the input private area
1076 //  2. decrypt the private buffer
1077 //  3. unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE
1078 //  Return Type: TPM_RC
1079 //      TPM_RCS_INTEGRITY       if the private area integrity is bad
1080 //      TPM_RC_SENSITIVE        unmarshal errors while unmarshaling TPMS_ENCRYPT
1081 //                              from input private
1082 //      TPM_RCS_SIZE            error during sensitive data unmarshaling
1083 //      TPM_RCS_VALUE           outer wrapper does not have an iV of the correct
1084 //                              size
1085 TPM_RC
PrivateToSensitive(TPM2B * inPrivate,TPM2B * name,OBJECT * parent,TPM_ALG_ID nameAlg,TPMT_SENSITIVE * sensitive)1086 PrivateToSensitive(
1087     TPM2B           *inPrivate,     // IN: input private structure
1088     TPM2B           *name,          // IN: the name of the object
1089     OBJECT          *parent,        // IN: parent object
1090     TPM_ALG_ID       nameAlg,       // IN: hash algorithm in public area.  It is
1091                                     //     passed separately because we only pass
1092                                     //     name, rather than the whole public area
1093                                     //     of the object.  This parameter is used in
1094                                     //     the following two cases: 1. primary
1095                                     //     objects. 2. duplication blob with inner
1096                                     //     wrap.  In other cases, this parameter
1097                                     //     will be ignored
1098     TPMT_SENSITIVE  *sensitive      // OUT: sensitive structure
1099     )
1100 {
1101     TPM_RC          result;
1102     BYTE            *buffer;
1103     INT32           size;
1104     BYTE            *sensitiveData; // pointer to the sensitive data
1105     UINT16          dataSize;
1106     UINT16          dataSizeInput;
1107     TPMI_ALG_HASH   hashAlg;        // hash algorithm for integrity
1108     UINT16          integritySize;
1109     UINT16          ivSize;
1110 //
1111     // Make sure that name is provided
1112     pAssert(name != NULL && name->size != 0);
1113 
1114     // Find the hash algorithm for integrity computation
1115     // For Temporary Object (parent == NULL) use self name algorithm;
1116     // Otherwise, using parent's name algorithm
1117     hashAlg = (parent == NULL) ? nameAlg : parent->publicArea.nameAlg;
1118 
1119     // unwrap outer
1120     result = UnwrapOuter(parent, name, hashAlg, NULL, TRUE,
1121                          inPrivate->size, inPrivate->buffer);
1122     if(result != TPM_RC_SUCCESS)
1123         return result;
1124     // Compute the inner integrity size.
1125     integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg);
1126 
1127     // Get iv size
1128     ivSize = GetIV2BSize(parent);
1129 
1130     // The starting of sensitive data and data size without outer wrapper
1131     sensitiveData = inPrivate->buffer + integritySize + ivSize;
1132     dataSize = inPrivate->size - integritySize - ivSize;
1133 
1134     // Unmarshal input data size
1135     buffer = sensitiveData;
1136     size = (INT32)dataSize;
1137     result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size);
1138     if(result == TPM_RC_SUCCESS)
1139     {
1140         if((dataSizeInput + sizeof(UINT16)) != dataSize)
1141             result = TPM_RC_SENSITIVE;
1142         else
1143         {
1144             // Unmarshal sensitive buffer to sensitive structure
1145             result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size);
1146             if(result != TPM_RC_SUCCESS || size != 0)
1147             {
1148                 result = TPM_RC_SENSITIVE;
1149             }
1150         }
1151     }
1152     return result;
1153 }
1154 
1155 //*** SensitiveToDuplicate()
1156 // This function prepare the duplication blob from the sensitive area.
1157 // The operations in this function:
1158 //  1. marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE
1159 //  2. apply inner wrap to the sensitive area if required
1160 //  3. apply outer wrap if required
1161 void
SensitiveToDuplicate(TPMT_SENSITIVE * sensitive,TPM2B * name,OBJECT * parent,TPM_ALG_ID nameAlg,TPM2B * seed,TPMT_SYM_DEF_OBJECT * symDef,TPM2B_DATA * innerSymKey,TPM2B_PRIVATE * outPrivate)1162 SensitiveToDuplicate(
1163     TPMT_SENSITIVE      *sensitive,     // IN: sensitive structure
1164     TPM2B               *name,          // IN: the name of the object
1165     OBJECT              *parent,        // IN: The new parent object
1166     TPM_ALG_ID           nameAlg,       // IN: hash algorithm in public area. It
1167                                         //     is passed separately because we
1168                                         //     only pass name, rather than the
1169                                         //     whole public area of the object.
1170     TPM2B               *seed,          // IN: the external seed. If external
1171                                         //     seed is provided with size of 0,
1172                                         //     no outer wrap should be applied
1173                                         //     to duplication blob.
1174     TPMT_SYM_DEF_OBJECT *symDef,        // IN: Symmetric key definition. If the
1175                                         //     symmetric key algorithm is NULL,
1176                                         //     no inner wrap should be applied.
1177     TPM2B_DATA          *innerSymKey,   // IN/OUT: a symmetric key may be
1178                                         //     provided to encrypt the inner
1179                                         //     wrap of a duplication blob. May
1180                                         //     be generated here if needed.
1181     TPM2B_PRIVATE       *outPrivate     // OUT: output private structure
1182     )
1183 {
1184     BYTE            *sensitiveData; // pointer to the sensitive data
1185     TPMI_ALG_HASH   outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap
1186     TPMI_ALG_HASH   innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap
1187     UINT16          dataSize;       // data blob size
1188     BOOL            doInnerWrap = FALSE;
1189     BOOL            doOuterWrap = FALSE;
1190 //
1191     // Make sure that name is provided
1192     pAssert(name != NULL && name->size != 0);
1193 
1194     // Make sure symDef and innerSymKey are not NULL
1195     pAssert(symDef != NULL && innerSymKey != NULL);
1196 
1197     // Starting of sensitive data without wrappers
1198     sensitiveData = outPrivate->t.buffer;
1199 
1200     // Find out if inner wrap is required
1201     if(symDef->algorithm != TPM_ALG_NULL)
1202     {
1203         doInnerWrap = TRUE;
1204 
1205         // Use self nameAlg as inner hash algorithm
1206         innerHash = nameAlg;
1207 
1208         // Adjust sensitive data pointer
1209         sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(innerHash);
1210     }
1211     // Find out if outer wrap is required
1212     if(seed->size != 0)
1213     {
1214         doOuterWrap = TRUE;
1215 
1216         // Use parent nameAlg as outer hash algorithm
1217         outerHash = parent->publicArea.nameAlg;
1218 
1219         // Adjust sensitive data pointer
1220         sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash);
1221     }
1222     // Marshal sensitive area
1223     dataSize = MarshalSensitive(NULL, sensitiveData, sensitive, nameAlg);
1224 
1225     // Apply inner wrap for duplication blob.  It includes both integrity and
1226     // encryption
1227     if(doInnerWrap)
1228     {
1229         BYTE            *innerBuffer = NULL;
1230         BOOL            symKeyInput = TRUE;
1231         innerBuffer = outPrivate->t.buffer;
1232         // Skip outer integrity space
1233         if(doOuterWrap)
1234             innerBuffer += sizeof(UINT16) + CryptHashGetDigestSize(outerHash);
1235         dataSize = ProduceInnerIntegrity(name, innerHash, dataSize,
1236                                          innerBuffer);
1237         // Generate inner encryption key if needed
1238         if(innerSymKey->t.size == 0)
1239         {
1240             innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8;
1241             CryptRandomGenerate(innerSymKey->t.size, innerSymKey->t.buffer);
1242 
1243             // TPM generates symmetric encryption.  Set the flag to FALSE
1244             symKeyInput = FALSE;
1245         }
1246         else
1247         {
1248             // assume the input key size should matches the symmetric definition
1249             pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8);
1250         }
1251 
1252         // Encrypt inner buffer in place
1253         CryptSymmetricEncrypt(innerBuffer, symDef->algorithm,
1254                               symDef->keyBits.sym, innerSymKey->t.buffer, NULL,
1255                               TPM_ALG_CFB, dataSize, innerBuffer);
1256 
1257         // If the symmetric encryption key is imported, clear the buffer for
1258         // output
1259         if(symKeyInput)
1260             innerSymKey->t.size = 0;
1261     }
1262     // Apply outer wrap for duplication blob.  It includes both integrity and
1263     // encryption
1264     if(doOuterWrap)
1265     {
1266         dataSize = ProduceOuterWrap(parent, name, outerHash, seed, FALSE,
1267                                     dataSize, outPrivate->t.buffer);
1268     }
1269     // Data size for output
1270     outPrivate->t.size = dataSize;
1271 
1272     return;
1273 }
1274 
1275 //*** DuplicateToSensitive()
1276 // Unwrap a duplication blob.  Check the integrity, decrypt and retrieve data
1277 // to a sensitive structure.
1278 // The operations in this function:
1279 //  1. check the integrity HMAC of the input private area
1280 //  2. decrypt the private buffer
1281 //  3. unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE
1282 //
1283 //  Return Type: TPM_RC
1284 //      TPM_RC_INSUFFICIENT      unmarshaling sensitive data from 'inPrivate' failed
1285 //      TPM_RC_INTEGRITY         'inPrivate' data integrity is broken
1286 //      TPM_RC_SIZE              unmarshaling sensitive data from 'inPrivate' failed
1287 TPM_RC
DuplicateToSensitive(TPM2B * inPrivate,TPM2B * name,OBJECT * parent,TPM_ALG_ID nameAlg,TPM2B * seed,TPMT_SYM_DEF_OBJECT * symDef,TPM2B * innerSymKey,TPMT_SENSITIVE * sensitive)1288 DuplicateToSensitive(
1289     TPM2B               *inPrivate,     // IN: input private structure
1290     TPM2B               *name,          // IN: the name of the object
1291     OBJECT              *parent,        // IN: the parent
1292     TPM_ALG_ID           nameAlg,       // IN: hash algorithm in public area.
1293     TPM2B               *seed,          // IN: an external seed may be provided.
1294                                         //     If external seed is provided with
1295                                         //     size of 0, no outer wrap is
1296                                         //     applied
1297     TPMT_SYM_DEF_OBJECT *symDef,        // IN: Symmetric key definition. If the
1298                                         //     symmetric key algorithm is NULL,
1299                                         //     no inner wrap is applied
1300     TPM2B               *innerSymKey,   // IN: a symmetric key may be provided
1301                                         //     to decrypt the inner wrap of a
1302                                         //     duplication blob.
1303     TPMT_SENSITIVE      *sensitive      // OUT: sensitive structure
1304     )
1305 {
1306     TPM_RC               result;
1307     BYTE                *buffer;
1308     INT32                size;
1309     BYTE                *sensitiveData; // pointer to the sensitive data
1310     UINT16               dataSize;
1311     UINT16               dataSizeInput;
1312 //
1313     // Make sure that name is provided
1314     pAssert(name != NULL && name->size != 0);
1315 
1316     // Make sure symDef and innerSymKey are not NULL
1317     pAssert(symDef != NULL && innerSymKey != NULL);
1318 
1319     // Starting of sensitive data
1320     sensitiveData = inPrivate->buffer;
1321     dataSize = inPrivate->size;
1322 
1323     // Find out if outer wrap is applied
1324     if(seed->size != 0)
1325     {
1326         // Use parent nameAlg as outer hash algorithm
1327         TPMI_ALG_HASH   outerHash = parent->publicArea.nameAlg;
1328 
1329         result = UnwrapOuter(parent, name, outerHash, seed, FALSE,
1330                              dataSize, sensitiveData);
1331         if(result != TPM_RC_SUCCESS)
1332             return result;
1333         // Adjust sensitive data pointer and size
1334         sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash);
1335         dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(outerHash);
1336     }
1337     // Find out if inner wrap is applied
1338     if(symDef->algorithm != TPM_ALG_NULL)
1339     {
1340         // assume the input key size matches the symmetric definition
1341         pAssert(innerSymKey->size == (symDef->keyBits.sym + 7) / 8);
1342 
1343         // Decrypt inner buffer in place
1344         CryptSymmetricDecrypt(sensitiveData, symDef->algorithm,
1345                               symDef->keyBits.sym, innerSymKey->buffer, NULL,
1346                               TPM_ALG_CFB, dataSize, sensitiveData);
1347         // Check inner integrity
1348         result = CheckInnerIntegrity(name, nameAlg, dataSize, sensitiveData);
1349         if(result != TPM_RC_SUCCESS)
1350             return result;
1351         // Adjust sensitive data pointer and size
1352         sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(nameAlg);
1353         dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(nameAlg);
1354     }
1355     // Unmarshal input data size
1356     buffer = sensitiveData;
1357     size = (INT32)dataSize;
1358     result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size);
1359     if(result == TPM_RC_SUCCESS)
1360     {
1361         if((dataSizeInput + sizeof(UINT16)) != dataSize)
1362             result = TPM_RC_SIZE;
1363         else
1364         {
1365             // Unmarshal sensitive buffer to sensitive structure
1366             result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size);
1367 
1368             // if the results is OK make sure that all the data was unmarshaled
1369             if(result == TPM_RC_SUCCESS && size != 0)
1370                 result = TPM_RC_SIZE;
1371         }
1372     }
1373     return result;
1374 }
1375 
1376 //*** SecretToCredential()
1377 // This function prepare the credential blob from a secret (a TPM2B_DIGEST)
1378 // The operations in this function:
1379 //  1. marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT
1380 //  2. encrypt the private buffer, excluding the leading integrity HMAC area
1381 //  3. compute integrity HMAC and append to the beginning of the buffer.
1382 //  4. Set the total size of TPM2B_ID_OBJECT buffer
1383 void
SecretToCredential(TPM2B_DIGEST * secret,TPM2B * name,TPM2B * seed,OBJECT * protector,TPM2B_ID_OBJECT * outIDObject)1384 SecretToCredential(
1385     TPM2B_DIGEST        *secret,        // IN: secret information
1386     TPM2B               *name,          // IN: the name of the object
1387     TPM2B               *seed,          // IN: an external seed.
1388     OBJECT              *protector,     // IN: the protector
1389     TPM2B_ID_OBJECT     *outIDObject    // OUT: output credential
1390     )
1391 {
1392     BYTE                *buffer;        // Auxiliary buffer pointer
1393     BYTE                *sensitiveData; // pointer to the sensitive data
1394     TPMI_ALG_HASH        outerHash;     // The hash algorithm for outer wrap
1395     UINT16               dataSize;      // data blob size
1396 //
1397     pAssert(secret != NULL && outIDObject != NULL);
1398 
1399     // use protector's name algorithm as outer hash ????
1400     outerHash = protector->publicArea.nameAlg;
1401 
1402     // Marshal secret area to credential buffer, leave space for integrity
1403     sensitiveData = outIDObject->t.credential
1404         + sizeof(UINT16) + CryptHashGetDigestSize(outerHash);
1405 // Marshal secret area
1406     buffer = sensitiveData;
1407     dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, NULL);
1408 
1409     // Apply outer wrap
1410     outIDObject->t.size = ProduceOuterWrap(protector, name, outerHash, seed, FALSE,
1411                                            dataSize, outIDObject->t.credential);
1412     return;
1413 }
1414 
1415 //*** CredentialToSecret()
1416 // Unwrap a credential.  Check the integrity, decrypt and retrieve data
1417 // to a TPM2B_DIGEST structure.
1418 // The operations in this function:
1419 //  1. check the integrity HMAC of the input credential area
1420 //  2. decrypt the credential buffer
1421 //  3. unmarshal TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST
1422 //
1423 //  Return Type: TPM_RC
1424 //      TPM_RC_INSUFFICIENT      error during credential unmarshaling
1425 //      TPM_RC_INTEGRITY         credential integrity is broken
1426 //      TPM_RC_SIZE              error during credential unmarshaling
1427 //      TPM_RC_VALUE             IV size does not match the encryption algorithm
1428 //                               block size
1429 TPM_RC
CredentialToSecret(TPM2B * inIDObject,TPM2B * name,TPM2B * seed,OBJECT * protector,TPM2B_DIGEST * secret)1430 CredentialToSecret(
1431     TPM2B               *inIDObject,    // IN: input credential blob
1432     TPM2B               *name,          // IN: the name of the object
1433     TPM2B               *seed,          // IN: an external seed.
1434     OBJECT              *protector,     // IN: the protector
1435     TPM2B_DIGEST        *secret         // OUT: secret information
1436     )
1437 {
1438     TPM_RC                   result;
1439     BYTE                    *buffer;
1440     INT32                    size;
1441     TPMI_ALG_HASH            outerHash;     // The hash algorithm for outer wrap
1442     BYTE                    *sensitiveData; // pointer to the sensitive data
1443     UINT16                   dataSize;
1444 //
1445     // use protector's name algorithm as outer hash
1446     outerHash = protector->publicArea.nameAlg;
1447 
1448     // Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point
1449     result = UnwrapOuter(protector, name, outerHash, seed, FALSE,
1450                          inIDObject->size, inIDObject->buffer);
1451     if(result == TPM_RC_SUCCESS)
1452     {
1453         // Compute the beginning of sensitive data
1454         sensitiveData = inIDObject->buffer
1455             + sizeof(UINT16) + CryptHashGetDigestSize(outerHash);
1456         dataSize = inIDObject->size
1457             - (sizeof(UINT16) + CryptHashGetDigestSize(outerHash));
1458         // Unmarshal secret buffer to TPM2B_DIGEST structure
1459         buffer = sensitiveData;
1460         size = (INT32)dataSize;
1461         result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size);
1462 
1463         // If there were no other unmarshaling errors, make sure that the
1464         // expected amount of data was recovered
1465         if(result == TPM_RC_SUCCESS && size != 0)
1466             return TPM_RC_SIZE;
1467     }
1468     return result;
1469 }
1470 
1471 //*** MemoryRemoveTrailingZeros()
1472 // This function is used to adjust the length of an authorization value.
1473 // It adjusts the size of the TPM2B so that it does not include octets
1474 // at the end of the buffer that contain zero.
1475 // The function returns the number of non-zero octets in the buffer.
1476 UINT16
MemoryRemoveTrailingZeros(TPM2B_AUTH * auth)1477 MemoryRemoveTrailingZeros(
1478     TPM2B_AUTH      *auth           // IN/OUT: value to adjust
1479     )
1480 {
1481     while((auth->t.size > 0) && (auth->t.buffer[auth->t.size - 1] == 0))
1482         auth->t.size--;
1483     return auth->t.size;
1484 }
1485 
1486 //*** SetLabelAndContext()
1487 // This function sets the label and context for a derived key. It is possible
1488 // that 'label' or 'context' can end up being an Empty Buffer.
1489 TPM_RC
SetLabelAndContext(TPMS_DERIVE * labelContext,TPM2B_SENSITIVE_DATA * sensitive)1490 SetLabelAndContext(
1491     TPMS_DERIVE             *labelContext,  // IN/OUT: the recovered label and
1492                                             //      context
1493     TPM2B_SENSITIVE_DATA    *sensitive      // IN: the sensitive data
1494     )
1495 {
1496     TPMS_DERIVE              sensitiveValue;
1497     TPM_RC                   result;
1498     INT32                    size;
1499     BYTE                    *buff;
1500 //
1501     // Unmarshal a TPMS_DERIVE from the TPM2B_SENSITIVE_DATA buffer
1502     // If there is something to unmarshal...
1503     if(sensitive->t.size != 0)
1504     {
1505         size = sensitive->t.size;
1506         buff = sensitive->t.buffer;
1507         result = TPMS_DERIVE_Unmarshal(&sensitiveValue, &buff, &size);
1508         if(result != TPM_RC_SUCCESS)
1509             return result;
1510         // If there was a label in the public area leave it there, otherwise, copy
1511         // the new value
1512         if(labelContext->label.t.size == 0)
1513             MemoryCopy2B(&labelContext->label.b, &sensitiveValue.label.b,
1514                          sizeof(labelContext->label.t.buffer));
1515         // if there was a context string in publicArea, it overrides
1516         if(labelContext->context.t.size == 0)
1517             MemoryCopy2B(&labelContext->context.b, &sensitiveValue.context.b,
1518                          sizeof(labelContext->label.t.buffer));
1519     }
1520     return TPM_RC_SUCCESS;
1521 }
1522 
1523 //*** UnmarshalToPublic()
1524 // Support function to unmarshal the template. This is used because the
1525 // Input may be a TPMT_TEMPLATE and that structure does not have the same
1526 // size as a TPMT_PUBLIC because of the difference between the 'unique' and
1527 // 'seed' fields.
1528 // If 'derive' is not NULL, then the 'seed' field is assumed to contain
1529 // a 'label' and 'context' that are unmarshaled into 'derive'.
1530 TPM_RC
UnmarshalToPublic(TPMT_PUBLIC * tOut,TPM2B_TEMPLATE * tIn,BOOL derivation,TPMS_DERIVE * labelContext)1531 UnmarshalToPublic(
1532     TPMT_PUBLIC         *tOut,       // OUT: output
1533     TPM2B_TEMPLATE      *tIn,        // IN:
1534     BOOL                 derivation, // IN: indicates if this is for a derivation
1535     TPMS_DERIVE         *labelContext// OUT: label and context if derivation
1536     )
1537 {
1538     BYTE                *buffer = tIn->t.buffer;
1539     INT32                size = tIn->t.size;
1540     TPM_RC               result;
1541 //
1542     // make sure that tOut is zeroed so that there are no remnants from previous
1543     // uses
1544     MemorySet(tOut, 0, sizeof(TPMT_PUBLIC));
1545     // Unmarshal the components of the TPMT_PUBLIC up to the unique field
1546     result = TPMI_ALG_PUBLIC_Unmarshal(&tOut->type, &buffer, &size);
1547     if(result != TPM_RC_SUCCESS)
1548         return result;
1549     result = TPMI_ALG_HASH_Unmarshal(&tOut->nameAlg, &buffer, &size, FALSE);
1550     if(result != TPM_RC_SUCCESS)
1551         return result;
1552     result = TPMA_OBJECT_Unmarshal(&tOut->objectAttributes, &buffer, &size);
1553     if(result != TPM_RC_SUCCESS)
1554         return result;
1555     result = TPM2B_DIGEST_Unmarshal(&tOut->authPolicy, &buffer, &size);
1556     if(result != TPM_RC_SUCCESS)
1557         return result;
1558     result = TPMU_PUBLIC_PARMS_Unmarshal(&tOut->parameters, &buffer, &size,
1559                                          tOut->type);
1560     if(result != TPM_RC_SUCCESS)
1561         return result;
1562     // Now unmarshal a TPMS_DERIVE if this is for derivation
1563     if(derivation)
1564         result = TPMS_DERIVE_Unmarshal(labelContext, &buffer, &size);
1565     else
1566         // otherwise, unmarshal a TPMU_PUBLIC_ID
1567         result = TPMU_PUBLIC_ID_Unmarshal(&tOut->unique, &buffer, &size,
1568                                           tOut->type);
1569     // Make sure the template was used up
1570     if((result == TPM_RC_SUCCESS) && (size != 0))
1571         result = TPM_RC_SIZE;
1572     return result;
1573 }
1574 
1575 
1576 //*** ObjectSetExternal()
1577 // Set the external attributes for an object.
1578 void
ObjectSetExternal(OBJECT * object)1579 ObjectSetExternal(
1580     OBJECT      *object
1581     )
1582 {
1583     object->attributes.external = SET;
1584 }