Line  | Count  | Source  | 
1  |  | // This file was extracted from the TCG Published  | 
2  |  | // Trusted Platform Module Library  | 
3  |  | // Part 4: Supporting Routines  | 
4  |  | // Family "2.0"  | 
5  |  | // Level 00 Revision 01.16  | 
6  |  | // October 30, 2014  | 
7  |  |  | 
8  |  | #include "InternalRoutines.h"  | 
9  |  | #include "Object_spt_fp.h"  | 
10  |  | #include "Platform.h"  | 
11  |  | //  | 
12  |  | //  | 
13  |  | //  | 
14  |  | //          Local Functions  | 
15  |  | //  | 
16  |  | //          EqualCryptSet()  | 
17  |  | //  | 
18  |  | //     Check if the crypto sets in two public areas are equal  | 
19  |  | //  | 
20  |  | //     Error Returns                     Meaning  | 
21  |  | //  | 
22  |  | //     TPM_RC_ASYMMETRIC                 mismatched parameters  | 
23  |  | //     TPM_RC_HASH                       mismatched name algorithm  | 
24  |  | //     TPM_RC_TYPE                       mismatched type  | 
25  |  | //  | 
26  |  | static TPM_RC  | 
27  |  | EqualCryptSet(  | 
28  |  |    TPMT_PUBLIC         *publicArea1,        // IN: public area 1  | 
29  |  |    TPMT_PUBLIC         *publicArea2         // IN: public area 2  | 
30  |  |    )  | 
31  | 0  | { | 
32  | 0  |    UINT16                   size1;  | 
33  | 0  |    UINT16                   size2;  | 
34  | 0  |    BYTE                     params1[sizeof(TPMU_PUBLIC_PARMS)];  | 
35  | 0  |    BYTE                     params2[sizeof(TPMU_PUBLIC_PARMS)];  | 
36  | 0  |    BYTE                     *buffer;  | 
37  | 0  |    INT32                    bufferSize;  | 
38  |  |    // Compare name hash  | 
39  | 0  |    if(publicArea1->nameAlg != publicArea2->nameAlg)  | 
40  | 0  |        return TPM_RC_HASH;  | 
41  |  |    // Compare algorithm  | 
42  | 0  |    if(publicArea1->type != publicArea2->type)  | 
43  | 0  |        return TPM_RC_TYPE;  | 
44  |  |    // TPMU_PUBLIC_PARMS field should be identical  | 
45  | 0  |    buffer = params1;  | 
46  | 0  |    bufferSize = sizeof(TPMU_PUBLIC_PARMS);  | 
47  | 0  |    size1 = TPMU_PUBLIC_PARMS_Marshal(&publicArea1->parameters, &buffer,  | 
48  | 0  |                                      &bufferSize, publicArea1->type);  | 
49  | 0  |    buffer = params2;  | 
50  | 0  |    bufferSize = sizeof(TPMU_PUBLIC_PARMS);  | 
51  | 0  |    size2 = TPMU_PUBLIC_PARMS_Marshal(&publicArea2->parameters, &buffer,  | 
52  | 0  |                                      &bufferSize, publicArea2->type);  | 
53  | 0  |    if(size1 != size2 || !MemoryEqual(params1, params2, size1))  | 
54  | 0  |        return TPM_RC_ASYMMETRIC;  | 
55  | 0  |    return TPM_RC_SUCCESS;  | 
56  | 0  | }  | 
57  |  | //  | 
58  |  | //  | 
59  |  | //          GetIV2BSize()  | 
60  |  | //  | 
61  |  | //     Get the size of TPM2B_IV in canonical form that will be append to the start of the sensitive data. It  | 
62  |  | //     includes both size of size field and size of iv data  | 
63  |  | //  | 
64  |  | //     Return Value                      Meaning  | 
65  |  | //  | 
66  |  | static UINT16  | 
67  |  | GetIV2BSize(  | 
68  |  |    TPM_HANDLE            protectorHandle           // IN: the protector handle  | 
69  |  |    )  | 
70  | 0  | { | 
71  | 0  |    OBJECT                   *protector = NULL; // Pointer to the protector object  | 
72  | 0  |    TPM_ALG_ID               symAlg;  | 
73  |  | //  | 
74  | 0  |    UINT16                    keyBits;  | 
75  |  |    // Determine the symmetric algorithm and size of key  | 
76  | 0  |    if(protectorHandle == TPM_RH_NULL)  | 
77  | 0  |    { | 
78  |  |        // Use the context encryption algorithm and key size  | 
79  | 0  |        symAlg = CONTEXT_ENCRYPT_ALG;  | 
80  | 0  |        keyBits = CONTEXT_ENCRYPT_KEY_BITS;  | 
81  | 0  |    }  | 
82  | 0  |    else  | 
83  | 0  |    { | 
84  | 0  |        protector = ObjectGet(protectorHandle);  | 
85  | 0  |        symAlg = protector->publicArea.parameters.asymDetail.symmetric.algorithm;  | 
86  | 0  |        keyBits= protector->publicArea.parameters.asymDetail.symmetric.keyBits.sym;  | 
87  | 0  |    }  | 
88  |  |    // The IV size is a UINT16 size field plus the block size of the symmetric  | 
89  |  |    // algorithm  | 
90  | 0  |    return sizeof(UINT16) + CryptGetSymmetricBlockSize(symAlg, keyBits);  | 
91  | 0  | }  | 
92  |  | //  | 
93  |  | //  | 
94  |  | //         ComputeProtectionKeyParms()  | 
95  |  | //  | 
96  |  | //     This function retrieves the symmetric protection key parameters for the sensitive data The parameters  | 
97  |  | //     retrieved from this function include encryption algorithm, key size in bit, and a TPM2B_SYM_KEY  | 
98  |  | //     containing the key material as well as the key size in bytes This function is used for any action that  | 
99  |  | //     requires encrypting or decrypting of the sensitive area of an object or a credential blob  | 
100  |  | //  | 
101  |  | static void  | 
102  |  | ComputeProtectionKeyParms(  | 
103  |  |    TPM_HANDLE          protectorHandle,       //   IN: the protector handle  | 
104  |  |    TPM_ALG_ID          hashAlg,               //   IN: hash algorithm for KDFa  | 
105  |  |    TPM2B_NAME         *name,                  //   IN: name of the object  | 
106  |  |    TPM2B_SEED         *seedIn,                //   IN: optional seed for duplication blob.  | 
107  |  |                                               //       For non duplication blob, this  | 
108  |  |                                               //       parameter should be NULL  | 
109  |  |    TPM_ALG_ID         *symAlg,                //   OUT: the symmetric algorithm  | 
110  |  |    UINT16             *keyBits,               //   OUT: the symmetric key size in bits  | 
111  |  |    TPM2B_SYM_KEY      *symKey                 //   OUT: the symmetric key  | 
112  |  |    )  | 
113  | 0  | { | 
114  | 0  |    TPM2B_SEED                *seed = NULL;  | 
115  | 0  |    OBJECT                    *protector = NULL; // Pointer to the protector  | 
116  |  |    // Determine the algorithms for the KDF and the encryption/decryption  | 
117  |  |    // For TPM_RH_NULL, using context settings  | 
118  | 0  |    if(protectorHandle == TPM_RH_NULL)  | 
119  | 0  |    { | 
120  |  |        // Use the context encryption algorithm and key size  | 
121  | 0  |        *symAlg = CONTEXT_ENCRYPT_ALG;  | 
122  | 0  |        symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES;  | 
123  | 0  |        *keyBits = CONTEXT_ENCRYPT_KEY_BITS;  | 
124  | 0  |    }  | 
125  | 0  |    else  | 
126  | 0  |    { | 
127  | 0  |        TPMT_SYM_DEF_OBJECT *symDef;  | 
128  | 0  |        protector = ObjectGet(protectorHandle);  | 
129  | 0  |        symDef = &protector->publicArea.parameters.asymDetail.symmetric;  | 
130  | 0  |        *symAlg = symDef->algorithm;  | 
131  | 0  |        *keyBits= symDef->keyBits.sym;  | 
132  | 0  |        symKey->t.size = (*keyBits + 7) / 8;  | 
133  | 0  |    }  | 
134  |  |    // Get seed for KDF  | 
135  | 0  |    seed = GetSeedForKDF(protectorHandle, seedIn);  | 
136  |  |    // KDFa to generate symmetric key and IV value  | 
137  | 0  |    KDFa(hashAlg, (TPM2B *)seed, "STORAGE", (TPM2B *)name, NULL,  | 
138  | 0  |         symKey->t.size * 8, symKey->t.buffer, NULL);  | 
139  | 0  |    return;  | 
140  | 0  | }  | 
141  |  | //  | 
142  |  | //  | 
143  |  | //           ComputeOuterIntegrity()  | 
144  |  | //  | 
145  |  | //      The sensitive area parameter is a buffer that holds a space for the integrity value and the marshaled  | 
146  |  | //      sensitive area. The caller should skip over the area set aside for the integrity value and compute the hash  | 
147  |  | //      of the remainder of the object. The size field of sensitive is in unmarshaled form and the sensitive area  | 
148  |  | //      contents is an array of bytes.  | 
149  |  | //  | 
150  |  | static void  | 
151  |  | ComputeOuterIntegrity(  | 
152  |  |    TPM2B_NAME          *name,                   //   IN: the name of the object  | 
153  |  |    TPM_HANDLE           protectorHandle,        //   IN: The handle of the object that  | 
154  |  |                                                 //       provides protection. For object, it  | 
155  |  |                                                 //       is parent handle. For credential, it  | 
156  |  |                                                 //       is the handle of encrypt object. For  | 
157  |  |                                                 //       a Temporary Object, it is TPM_RH_NULL  | 
158  |  |    TPMI_ALG_HASH        hashAlg,                //   IN: algorithm to use for integrity  | 
159  |  |    TPM2B_SEED          *seedIn,                 //   IN: an external seed may be provided for  | 
160  |  |                                                 //       duplication blob. For non duplication  | 
161  |  |                                                 //       blob, this parameter should be NULL  | 
162  |  |    UINT32               sensitiveSize,          //   IN: size of the marshaled sensitive data  | 
163  |  |    BYTE                *sensitiveData,          //   IN: sensitive area  | 
164  |  |    TPM2B_DIGEST        *integrity               //   OUT: integrity  | 
165  |  |    )  | 
166  | 0  | { | 
167  | 0  |    HMAC_STATE               hmacState;  | 
168  | 0  |    TPM2B_DIGEST             hmacKey;  | 
169  | 0  |    TPM2B_SEED               *seed = NULL;  | 
170  |  |    // Get seed for KDF  | 
171  | 0  |    seed = GetSeedForKDF(protectorHandle, seedIn);  | 
172  |  |    // Determine the HMAC key bits  | 
173  | 0  |    hmacKey.t.size = CryptGetHashDigestSize(hashAlg);  | 
174  |  |    // KDFa to generate HMAC key  | 
175  | 0  |    KDFa(hashAlg, (TPM2B *)seed, "INTEGRITY", NULL, NULL,  | 
176  | 0  |         hmacKey.t.size * 8, hmacKey.t.buffer, NULL);  | 
177  |  |    // Start HMAC and get the size of the digest which will become the integrity  | 
178  | 0  |    integrity->t.size = CryptStartHMAC2B(hashAlg, &hmacKey.b, &hmacState);  | 
179  |  |    // Adding the marshaled sensitive area to the integrity value  | 
180  | 0  |    CryptUpdateDigest(&hmacState, sensitiveSize, sensitiveData);  | 
181  |  |    // Adding name  | 
182  | 0  |    CryptUpdateDigest2B(&hmacState, (TPM2B *)name);  | 
183  |  |    // Compute HMAC  | 
184  | 0  |    CryptCompleteHMAC2B(&hmacState, &integrity->b);  | 
185  | 0  |    return;  | 
186  | 0  | }  | 
187  |  | //  | 
188  |  | //  | 
189  |  | //           ComputeInnerIntegrity()  | 
190  |  | //  | 
191  |  | //      This function computes the integrity of an inner wrap  | 
192  |  | //  | 
193  |  | static void  | 
194  |  | ComputeInnerIntegrity(  | 
195  |  |     TPM_ALG_ID           hashAlg,           //   IN: hash algorithm for inner wrap  | 
196  |  |     TPM2B_NAME          *name,              //   IN: the name of the object  | 
197  |  |     UINT16               dataSize,          //   IN: the size of sensitive data  | 
198  |  |     BYTE                *sensitiveData,     //   IN: sensitive data  | 
199  |  |     TPM2B_DIGEST        *integrity          //   OUT: inner integrity  | 
200  |  |     )  | 
201  | 0  | { | 
202  | 0  |     HASH_STATE          hashState;  | 
203  |  |     // Start hash and get the size of the digest which will become the integrity  | 
204  | 0  |     integrity->t.size = CryptStartHash(hashAlg, &hashState);  | 
205  |  |     // Adding the marshaled sensitive area to the integrity value  | 
206  | 0  |     CryptUpdateDigest(&hashState, dataSize, sensitiveData);  | 
207  |  |     // Adding name  | 
208  | 0  |     CryptUpdateDigest2B(&hashState, &name->b);  | 
209  |  |     // Compute hash  | 
210  | 0  |     CryptCompleteHash2B(&hashState, &integrity->b);  | 
211  | 0  |     return;  | 
212  | 0  | }  | 
213  |  | //  | 
214  |  | //  | 
215  |  | //           ProduceInnerIntegrity()  | 
216  |  | //  | 
217  |  | //      This function produces an inner integrity for regular private, credential or duplication blob It requires the  | 
218  |  | //      sensitive data being marshaled to the innerBuffer, with the leading bytes reserved for integrity hash. It  | 
219  |  | //      assume the sensitive data starts at address (innerBuffer + integrity size). This function integrity at the  | 
220  |  | //      beginning of the inner buffer It returns the total size of buffer with the inner wrap  | 
221  |  | //  | 
222  |  | static UINT16  | 
223  |  | ProduceInnerIntegrity(  | 
224  |  |     TPM2B_NAME          *name,              //   IN: the name of the object  | 
225  |  |     TPM_ALG_ID           hashAlg,           //   IN: hash algorithm for inner wrap  | 
226  |  |     UINT16               dataSize,          //   IN: the size of sensitive data, excluding the  | 
227  |  |                                             //       leading integrity buffer size  | 
228  |  |     BYTE                *innerBuffer        //   IN/OUT: inner buffer with sensitive data in  | 
229  |  |                                             //       it. At input, the leading bytes of this  | 
230  |  |                                             //       buffer is reserved for integrity  | 
231  |  |     )  | 
232  | 0  | { | 
233  | 0  |     BYTE                     *sensitiveData; // pointer to the sensitive data  | 
234  | 0  |     TPM2B_DIGEST             integrity;  | 
235  | 0  |     UINT16                   integritySize;  | 
236  | 0  |     BYTE                     *buffer;             // Auxiliary buffer pointer  | 
237  | 0  |     INT32                    bufferSize;  | 
238  |  |     // sensitiveData points to the beginning of sensitive data in innerBuffer  | 
239  | 0  |     integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);  | 
240  | 0  |     sensitiveData = innerBuffer + integritySize;  | 
241  | 0  |     ComputeInnerIntegrity(hashAlg, name, dataSize, sensitiveData, &integrity);  | 
242  |  |     // Add integrity at the beginning of inner buffer  | 
243  | 0  |     buffer = innerBuffer;  | 
244  | 0  |     bufferSize = sizeof(TPM2B_DIGEST);  | 
245  | 0  |     TPM2B_DIGEST_Marshal(&integrity, &buffer, &bufferSize);  | 
246  | 0  |     return dataSize + integritySize;  | 
247  | 0  | }  | 
248  |  | //  | 
249  |  | //  | 
250  |  | //           CheckInnerIntegrity()  | 
251  |  | //  | 
252  |  | //      This function check integrity of inner blob  | 
253  |  | //  | 
254  |  | //      Error Returns                     Meaning  | 
255  |  | //  | 
256  |  | //      TPM_RC_INTEGRITY                  if the outer blob integrity is bad  | 
257  |  | //      unmarshal errors                  unmarshal errors while unmarshaling integrity  | 
258  |  | //  | 
259  |  | static TPM_RC  | 
260  |  | CheckInnerIntegrity(  | 
261  |  |     TPM2B_NAME          *name,                //   IN: the name of the object  | 
262  |  |     TPM_ALG_ID           hashAlg,             //   IN: hash algorithm for inner wrap  | 
263  |  |     UINT16               dataSize,            //   IN: the size of sensitive data, including the  | 
264  |  |                                               //       leading integrity buffer size  | 
265  |  |     BYTE                *innerBuffer          //   IN/OUT: inner buffer with sensitive data in  | 
266  |  |                                               //       it  | 
267  |  |     )  | 
268  | 0  | { | 
269  | 0  |     TPM_RC              result;  | 
270  | 0  |     TPM2B_DIGEST        integrity;  | 
271  | 0  |     TPM2B_DIGEST        integrityToCompare;  | 
272  | 0  |     BYTE                *buffer;                          // Auxiliary buffer pointer  | 
273  | 0  |     INT32               size;  | 
274  |  |     // Unmarshal integrity  | 
275  | 0  |     buffer = innerBuffer;  | 
276  | 0  |     size = (INT32) dataSize;  | 
277  | 0  |     result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);  | 
278  | 0  |     if(result == TPM_RC_SUCCESS)  | 
279  | 0  |     { | 
280  |  |         // Compute integrity to compare  | 
281  | 0  |         ComputeInnerIntegrity(hashAlg, name, (UINT16) size, buffer,  | 
282  | 0  |                               &integrityToCompare);  | 
283  |  |          // Compare outer blob integrity  | 
284  | 0  |          if(!Memory2BEqual(&integrity.b, &integrityToCompare.b))  | 
285  | 0  |              result = TPM_RC_INTEGRITY;  | 
286  | 0  |     }  | 
287  | 0  |     return result;  | 
288  | 0  | }  | 
289  |  | //  | 
290  |  | //  | 
291  |  | //           Public Functions  | 
292  |  | //  | 
293  |  | //           AreAttributesForParent()  | 
294  |  | //  | 
295  |  | //      This function is called by create, load, and import functions.  | 
296  |  | //  | 
297  |  | //      Return Value                      Meaning  | 
298  |  | //  | 
299  |  | //      TRUE                              properties are those of a parent  | 
300  |  | //      FALSE                             properties are not those of a parent  | 
301  |  | //  | 
302  |  | BOOL  | 
303  |  | AreAttributesForParent(  | 
304  |  |    OBJECT             *parentObject        // IN: parent handle  | 
305  |  |    )  | 
306  | 0  | { | 
307  |  |    // This function is only called when a parent is needed. Any  | 
308  |  |    // time a "parent" is used, it must be authorized. When  | 
309  |  |    // the authorization is checked, both the public and sensitive  | 
310  |  |    // areas must be loaded. Just make sure...  | 
311  | 0  |    pAssert(parentObject->attributes.publicOnly == CLEAR);  | 
312  | 0  |    if(ObjectDataIsStorage(&parentObject->publicArea))  | 
313  | 0  |        return TRUE;  | 
314  | 0  |    else  | 
315  | 0  |        return FALSE;  | 
316  | 0  | }  | 
317  |  | //  | 
318  |  | //  | 
319  |  | //          SchemeChecks()  | 
320  |  | //  | 
321  |  | //      This function validates the schemes in the public area of an object. This function is called by  | 
322  |  | //      TPM2_LoadExternal() and PublicAttributesValidation().  | 
323  |  | //  | 
324  |  | //      Error Returns                   Meaning  | 
325  |  | //  | 
326  |  | //      TPM_RC_ASYMMETRIC               non-duplicable storage key and its parent have different public  | 
327  |  | //                                      parameters  | 
328  |  | //      TPM_RC_ATTRIBUTES               attempt to inject sensitive data for an asymmetric key; or attempt to  | 
329  |  | //                                      create a symmetric cipher key that is not a decryption key  | 
330  |  | //      TPM_RC_HASH                     non-duplicable storage key and its parent have different name  | 
331  |  | //                                      algorithm  | 
332  |  | //      TPM_RC_KDF                      incorrect KDF specified for decrypting keyed hash object  | 
333  |  | //      TPM_RC_KEY                      invalid key size values in an asymmetric key public area  | 
334  |  | //      TPM_RC_SCHEME                   inconsistent attributes decrypt, sign, restricted and key's scheme ID;  | 
335  |  | //                                      or hash algorithm is inconsistent with the scheme ID for keyed hash  | 
336  |  | //                                      object  | 
337  |  | //      TPM_RC_SYMMETRIC                a storage key with no symmetric algorithm specified; or non-storage  | 
338  |  | //                                      key with symmetric algorithm different from TPM_ALG_NULL  | 
339  |  | //      TPM_RC_TYPE                     unexpected object type; or non-duplicable storage key and its parent  | 
340  |  | //                                      have different types  | 
341  |  | //  | 
342  |  | TPM_RC  | 
343  |  | SchemeChecks(  | 
344  |  |    BOOL                load,               // IN: TRUE if load checks, FALSE if  | 
345  |  |                                            //     TPM2_Create()  | 
346  |  |    TPMI_DH_OBJECT      parentHandle,       // IN: input parent handle  | 
347  |  |    TPMT_PUBLIC        *publicArea          // IN: public area of the object  | 
348  |  |    )  | 
349  | 55  | { | 
350  |  |    // Checks for an asymmetric key  | 
351  | 55  |    if(CryptIsAsymAlgorithm(publicArea->type))  | 
352  | 55  |    { | 
353  | 55  |        TPMT_ASYM_SCHEME        *keyScheme;  | 
354  | 55  |        keyScheme = &publicArea->parameters.asymDetail.scheme;  | 
355  |  |          // An asymmetric key can't be injected  | 
356  |  |          // This is only checked when creating an object  | 
357  | 55  |          if(!load && (publicArea->objectAttributes.sensitiveDataOrigin == CLEAR))  | 
358  | 0  |              return TPM_RC_ATTRIBUTES;  | 
359  | 55  |          if(load && !CryptAreKeySizesConsistent(publicArea))  | 
360  | 0  |              return TPM_RC_KEY;  | 
361  |  |          // Keys that are both signing and decrypting must have TPM_ALG_NULL  | 
362  |  |          // for scheme  | 
363  | 55  |          if(     publicArea->objectAttributes.sign == SET  | 
364  | 39  |              && publicArea->objectAttributes.decrypt == SET  | 
365  | 2  |              && keyScheme->scheme != TPM_ALG_NULL)  | 
366  | 0  |               return TPM_RC_SCHEME;  | 
367  |  |          // A restrict sign key must have a non-NULL scheme  | 
368  | 55  |          if(     publicArea->objectAttributes.restricted == SET  | 
369  | 0  |              && publicArea->objectAttributes.sign == SET  | 
370  | 0  |              && keyScheme->scheme == TPM_ALG_NULL)  | 
371  | 0  |              return TPM_RC_SCHEME;  | 
372  |  |          // Keys must have a valid sign or decrypt scheme, or a TPM_ALG_NULL  | 
373  |  |          // scheme  | 
374  |  |          // NOTE: The unmarshaling for a public area will unmarshal based on the  | 
375  |  |          // object type. If the type is an RSA key, then only RSA schemes will be  | 
376  |  |          // allowed because a TPMI_ALG_RSA_SCHEME will be unmarshaled and it  | 
377  |  |          // consists only of those algorithms that are allowed with an RSA key.  | 
378  |  |          // This means that there is no need to again make sure that the algorithm  | 
379  |  |          // is compatible with the object type.  | 
380  | 55  |          if(    keyScheme->scheme != TPM_ALG_NULL  | 
381  | 53  |              && (    (    publicArea->objectAttributes.sign == SET  | 
382  | 37  |                        && !CryptIsSignScheme(keyScheme->scheme)  | 
383  | 53  |                      )  | 
384  | 53  |                   || (    publicArea->objectAttributes.decrypt == SET  | 
385  | 4  |                        && !CryptIsDecryptScheme(keyScheme->scheme)  | 
386  | 53  |                      )  | 
387  | 53  |                 )  | 
388  | 55  |            )  | 
389  | 0  |               return TPM_RC_SCHEME;  | 
390  |  |        // Special checks for an ECC key  | 
391  | 55  | #ifdef TPM_ALG_ECC  | 
392  | 55  |        if(publicArea->type == TPM_ALG_ECC)  | 
393  | 6  |        { | 
394  | 6  |            TPM_ECC_CURVE        curveID = publicArea->parameters.eccDetail.curveID;  | 
395  | 6  |            const TPMT_ECC_SCHEME *curveScheme = CryptGetCurveSignScheme(curveID);  | 
396  |  |            // The curveId must be valid or the unmarshaling is busted.  | 
397  | 6  |            pAssert(curveScheme != NULL);  | 
398  |  |              // If the curveID requires a specific scheme, then the key must select  | 
399  |  |              // the same scheme  | 
400  | 6  |              if(curveScheme->scheme != TPM_ALG_NULL)  | 
401  | 0  |              { | 
402  | 0  |                  if(keyScheme->scheme != curveScheme->scheme)  | 
403  | 0  |                       return TPM_RC_SCHEME;  | 
404  |  |                  // The scheme can allow any hash, or not...  | 
405  | 0  |                  if(    curveScheme->details.anySig.hashAlg != TPM_ALG_NULL  | 
406  | 0  |                      && (   keyScheme->details.anySig.hashAlg  | 
407  | 0  |                          != curveScheme->details.anySig.hashAlg  | 
408  | 0  |                         )  | 
409  | 0  |                    )  | 
410  | 0  |                       return TPM_RC_SCHEME;  | 
411  | 0  |              }  | 
412  |  |              // For now, the KDF must be TPM_ALG_NULL  | 
413  | 6  |              if(publicArea->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL)  | 
414  | 0  |                  return TPM_RC_KDF;  | 
415  | 6  |          }  | 
416  | 55  | #endif  | 
417  |  |          // Checks for a storage key (restricted + decryption)  | 
418  | 55  |          if(   publicArea->objectAttributes.restricted == SET  | 
419  | 0  |               && publicArea->objectAttributes.decrypt == SET)  | 
420  | 0  |         { | 
421  |  |               // A storage key must have a valid protection key  | 
422  | 0  |               if(    publicArea->parameters.asymDetail.symmetric.algorithm  | 
423  | 0  |                   == TPM_ALG_NULL)  | 
424  | 0  |                    return TPM_RC_SYMMETRIC;  | 
425  |  |               // A storage key must have a null scheme  | 
426  | 0  |               if(publicArea->parameters.asymDetail.scheme.scheme != TPM_ALG_NULL)  | 
427  | 0  |                   return TPM_RC_SCHEME;  | 
428  |  |               // A storage key must match its parent algorithms unless  | 
429  |  |               // it is duplicable or a primary (including Temporary Primary Objects)  | 
430  | 0  |               if(    HandleGetType(parentHandle) != TPM_HT_PERMANENT  | 
431  | 0  |                   && publicArea->objectAttributes.fixedParent == SET  | 
432  | 0  |                 )  | 
433  | 0  |               { | 
434  |  |                    // If the object to be created is a storage key, and is fixedParent,  | 
435  |  |                    // its crypto set has to match its parent's crypto set. TPM_RC_TYPE,  | 
436  |  |                    // TPM_RC_HASH or TPM_RC_ASYMMETRIC may be returned at this point  | 
437  | 0  |                    return EqualCryptSet(publicArea,  | 
438  | 0  |                                         &(ObjectGet(parentHandle)->publicArea));  | 
439  | 0  |               }  | 
440  | 0  |         }  | 
441  | 55  |         else  | 
442  | 55  |         { | 
443  |  |               // Non-storage keys must have TPM_ALG_NULL for the symmetric algorithm  | 
444  | 55  |               if(    publicArea->parameters.asymDetail.symmetric.algorithm  | 
445  | 55  |                   != TPM_ALG_NULL)  | 
446  | 0  |                    return TPM_RC_SYMMETRIC;  | 
447  | 55  |        }// End of asymmetric decryption key checks  | 
448  | 55  |    } // End of asymmetric checks  | 
449  |  |    // Check for bit attributes  | 
450  | 0  |    else if(publicArea->type == TPM_ALG_KEYEDHASH)  | 
451  | 0  |    { | 
452  | 0  |        TPMT_KEYEDHASH_SCHEME    *scheme  | 
453  | 0  |            = &publicArea->parameters.keyedHashDetail.scheme;  | 
454  |  |        // If both sign and decrypt are set the scheme must be TPM_ALG_NULL  | 
455  |  |        // and the scheme selected when the key is used.  | 
456  |  |        // If neither sign nor decrypt is set, the scheme must be TPM_ALG_NULL  | 
457  |  |        // because this is a data object.  | 
458  | 0  |        if(      publicArea->objectAttributes.sign  | 
459  | 0  |            == publicArea->objectAttributes.decrypt)  | 
460  | 0  |        { | 
461  | 0  |            if(scheme->scheme != TPM_ALG_NULL)  | 
462  | 0  |                 return TPM_RC_SCHEME;  | 
463  | 0  |            return TPM_RC_SUCCESS;  | 
464  | 0  |        }  | 
465  |  |        // If this is a decryption key, make sure that is is XOR and that there  | 
466  |  |        // is a KDF  | 
467  | 0  |        else if(publicArea->objectAttributes.decrypt)  | 
468  | 0  |        { | 
469  | 0  |            if(    scheme->scheme != TPM_ALG_XOR  | 
470  | 0  |                || scheme->details.xor_.hashAlg == TPM_ALG_NULL)  | 
471  | 0  |                 return TPM_RC_SCHEME;  | 
472  | 0  |            if(scheme->details.xor_.kdf == TPM_ALG_NULL)  | 
473  | 0  |                 return TPM_RC_KDF;  | 
474  | 0  |            return TPM_RC_SUCCESS;  | 
475  | 0  |         }  | 
476  |  |         // only supported signing scheme for keyedHash object is HMAC  | 
477  | 0  |         if(    scheme->scheme != TPM_ALG_HMAC  | 
478  | 0  |             || scheme->details.hmac.hashAlg == TPM_ALG_NULL)  | 
479  | 0  |              return TPM_RC_SCHEME;  | 
480  |  |          // end of the checks for keyedHash  | 
481  | 0  |          return TPM_RC_SUCCESS;  | 
482  | 0  |    }  | 
483  | 0  |    else if (publicArea->type == TPM_ALG_SYMCIPHER)  | 
484  | 0  |    { | 
485  |  |        // Must be a decrypting key and may not be a signing key  | 
486  | 0  |        if(    publicArea->objectAttributes.decrypt == CLEAR  | 
487  | 0  |            || publicArea->objectAttributes.sign == SET  | 
488  | 0  |          )  | 
489  | 0  |             return TPM_RC_ATTRIBUTES;  | 
490  | 0  |    }  | 
491  | 0  |    else  | 
492  | 0  |        return TPM_RC_TYPE;  | 
493  | 55  |    return TPM_RC_SUCCESS;  | 
494  | 55  | }  | 
495  |  | //  | 
496  |  | //  | 
497  |  | //          PublicAttributesValidation()  | 
498  |  | //  | 
499  |  | //      This function validates the values in the public area of an object. This function is called by  | 
500  |  | //      TPM2_Create(), TPM2_Load(), and TPM2_CreatePrimary()  | 
501  |  | //  | 
502  |  | //      Error Returns                     Meaning  | 
503  |  | //  | 
504  |  | //      TPM_RC_ASYMMETRIC                 non-duplicable storage key and its parent have different public  | 
505  |  | //                                        parameters  | 
506  |  | //      TPM_RC_ATTRIBUTES                 fixedTPM, fixedParent, or encryptedDuplication attributes are  | 
507  |  | //                                        inconsistent between themselves or with those of the parent object;  | 
508  |  | //                                        inconsistent restricted, decrypt and sign attributes; attempt to inject  | 
509  |  | //                                        sensitive data for an asymmetric key; attempt to create a symmetric  | 
510  |  | //                                        cipher key that is not a decryption key  | 
511  |  | //      TPM_RC_HASH                       non-duplicable storage key and its parent have different name  | 
512  |  | //                                        algorithm  | 
513  |  | //      TPM_RC_KDF                        incorrect KDF specified for decrypting keyed hash object  | 
514  |  | //      TPM_RC_KEY                        invalid key size values in an asymmetric key public area  | 
515  |  | //      TPM_RC_SCHEME                     inconsistent attributes decrypt, sign, restricted and key's scheme ID;  | 
516  |  | //                                        or hash algorithm is inconsistent with the scheme ID for keyed hash  | 
517  |  | //                                        object  | 
518  |  | //      TPM_RC_SIZE                       authPolicy size does not match digest size of the name algorithm in  | 
519  |  | //                                        publicArea  | 
520  |  | //      TPM_RC_SYMMETRIC                  a storage key with no symmetric algorithm specified; or non-storage  | 
521  |  | //                                        key with symmetric algorithm different from TPM_ALG_NULL  | 
522  |  | //      TPM_RC_TYPE                       unexpected object type; or non-duplicable storage key and its parent  | 
523  |  | //                                        have different types  | 
524  |  | //  | 
525  |  | TPM_RC  | 
526  |  | PublicAttributesValidation(  | 
527  |  |    BOOL                load,                 // IN: TRUE if load checks, FALSE if  | 
528  |  |                                              //     TPM2_Create()  | 
529  |  |    TPMI_DH_OBJECT      parentHandle,         // IN: input parent handle  | 
530  |  |    TPMT_PUBLIC        *publicArea            // IN: public area of the object  | 
531  |  |    )  | 
532  | 2  | { | 
533  | 2  |    OBJECT                  *parentObject = NULL;  | 
534  | 2  |    if(HandleGetType(parentHandle) != TPM_HT_PERMANENT)  | 
535  | 0  |        parentObject = ObjectGet(parentHandle);  | 
536  | 2  |     if (publicArea->nameAlg == TPM_ALG_NULL)  | 
537  | 0  |         return TPM_RC_HASH;  | 
538  |  |     // Check authPolicy digest consistency  | 
539  | 2  |     if(   publicArea->authPolicy.t.size != 0  | 
540  | 0  |        && (    publicArea->authPolicy.t.size  | 
541  | 0  |             != CryptGetHashDigestSize(publicArea->nameAlg)  | 
542  | 0  |           )  | 
543  | 2  |       )  | 
544  | 0  |         return TPM_RC_SIZE;  | 
545  |  |     // If the parent is fixedTPM (including a Primary Object) the object must have  | 
546  |  |     // the same value for fixedTPM and fixedParent  | 
547  | 2  |     if(     parentObject == NULL  | 
548  | 0  |         || parentObject->publicArea.objectAttributes.fixedTPM == SET)  | 
549  | 2  |     { | 
550  | 2  |         if(    publicArea->objectAttributes.fixedParent  | 
551  | 2  |             != publicArea->objectAttributes.fixedTPM  | 
552  | 2  |           )  | 
553  | 0  |              return TPM_RC_ATTRIBUTES;  | 
554  | 2  |     }  | 
555  | 0  |     else  | 
556  |  |         // The parent is not fixedTPM so the object can't be fixedTPM  | 
557  | 0  |         if(publicArea->objectAttributes.fixedTPM == SET)  | 
558  | 0  |              return TPM_RC_ATTRIBUTES;  | 
559  |  |     // A restricted object cannot be both sign and decrypt and it can't be neither  | 
560  |  |     // sign nor decrypt  | 
561  | 2  |     if (    publicArea->objectAttributes.restricted == SET  | 
562  | 0  |          && (    publicArea->objectAttributes.decrypt  | 
563  | 0  |               == publicArea->objectAttributes.sign)  | 
564  | 2  |        )  | 
565  | 0  |          return TPM_RC_ATTRIBUTES;  | 
566  |  |     // A fixedTPM object can not have encryptedDuplication bit SET  | 
567  | 2  |     if(    publicArea->objectAttributes.fixedTPM == SET  | 
568  | 0  |         && publicArea->objectAttributes.encryptedDuplication == SET)  | 
569  | 0  |         return TPM_RC_ATTRIBUTES;  | 
570  |  |     // If a parent object has fixedTPM CLEAR, the child must have the  | 
571  |  |     // same encryptedDuplication value as its parent.  | 
572  |  |     // Primary objects are considered to have a fixedTPM parent (the seeds).  | 
573  | 2  |    if(       (   parentObject != NULL  | 
574  | 0  |               && parentObject->publicArea.objectAttributes.fixedTPM == CLEAR)  | 
575  |  |        // Get here if parent is not fixed TPM  | 
576  | 0  |        && (     publicArea->objectAttributes.encryptedDuplication  | 
577  | 0  |              != parentObject->publicArea.objectAttributes.encryptedDuplication  | 
578  | 0  |            )  | 
579  | 2  |       )  | 
580  | 0  |         return TPM_RC_ATTRIBUTES;  | 
581  | 2  |    return SchemeChecks(load, parentHandle, publicArea);  | 
582  | 2  | }  | 
583  |  | //  | 
584  |  | //  | 
585  |  | //            FillInCreationData()  | 
586  |  | //  | 
587  |  | //      Fill in creation data for an object.  | 
588  |  | //  | 
589  |  | void  | 
590  |  | FillInCreationData(  | 
591  |  |     TPMI_DH_OBJECT                     parentHandle,    //   IN: handle of parent  | 
592  |  |     TPMI_ALG_HASH                      nameHashAlg,     //   IN: name hash algorithm  | 
593  |  |     TPML_PCR_SELECTION                *creationPCR,     //   IN: PCR selection  | 
594  |  |     TPM2B_DATA                        *outsideData,     //   IN: outside data  | 
595  |  |     TPM2B_CREATION_DATA               *outCreation,     //   OUT: creation data for output  | 
596  |  |     TPM2B_DIGEST                      *creationDigest   //   OUT: creation digest  | 
597  |  | //  | 
598  |  |    )  | 
599  | 2  | { | 
600  | 2  |    BYTE                     creationBuffer[sizeof(TPMS_CREATION_DATA)];  | 
601  | 2  |    BYTE                    *buffer;  | 
602  | 2  |    INT32                    bufferSize;  | 
603  | 2  |    HASH_STATE               hashState;  | 
604  |  |    // Fill in TPMS_CREATION_DATA in outCreation  | 
605  |  |    // Compute PCR digest  | 
606  | 2  |    PCRComputeCurrentDigest(nameHashAlg, creationPCR,  | 
607  | 2  |                            &outCreation->t.creationData.pcrDigest);  | 
608  |  |    // Put back PCR selection list  | 
609  | 2  |    outCreation->t.creationData.pcrSelect = *creationPCR;  | 
610  |  |    // Get locality  | 
611  | 2  |    outCreation->t.creationData.locality  | 
612  | 2  |        = LocalityGetAttributes(_plat__LocalityGet());  | 
613  | 2  |    outCreation->t.creationData.parentNameAlg = TPM_ALG_NULL;  | 
614  |  |    // If the parent is is either a primary seed or TPM_ALG_NULL, then the Name  | 
615  |  |    // and QN of the parent are the parent's handle.  | 
616  | 2  |    if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)  | 
617  | 2  |    { | 
618  | 2  |        BYTE         *buffer = &outCreation->t.creationData.parentName.t.name[0];  | 
619  | 2  |        INT32         bufferSize = sizeof(TPM_HANDLE);  | 
620  | 2  |        outCreation->t.creationData.parentName.t.size =  | 
621  | 2  |             TPM_HANDLE_Marshal(&parentHandle, &buffer, &bufferSize);  | 
622  |  |          // Parent qualified name of a Temporary Object is the same as parent's  | 
623  |  |          // name  | 
624  | 2  |          MemoryCopy2B(&outCreation->t.creationData.parentQualifiedName.b,  | 
625  | 2  |                       &outCreation->t.creationData.parentName.b,  | 
626  | 2  |                      sizeof(outCreation->t.creationData.parentQualifiedName.t.name));  | 
627  | 2  |    }  | 
628  | 0  |    else           // Regular object  | 
629  | 0  |    { | 
630  | 0  |        OBJECT              *parentObject = ObjectGet(parentHandle);  | 
631  |  |          // Set name algorithm  | 
632  | 0  |          outCreation->t.creationData.parentNameAlg =  | 
633  | 0  |              parentObject->publicArea.nameAlg;  | 
634  |  |          // Copy parent name  | 
635  | 0  |          outCreation->t.creationData.parentName = parentObject->name;  | 
636  |  |          // Copy parent qualified name  | 
637  | 0  |          outCreation->t.creationData.parentQualifiedName =  | 
638  | 0  |              parentObject->qualifiedName;  | 
639  | 0  |    }  | 
640  |  |    // Copy outside information  | 
641  | 2  |    outCreation->t.creationData.outsideInfo = *outsideData;  | 
642  |  |    // Marshal creation data to canonical form  | 
643  | 2  |    buffer = creationBuffer;  | 
644  | 2  |    bufferSize = sizeof(TPMS_CREATION_DATA);  | 
645  | 2  |    outCreation->t.size = TPMS_CREATION_DATA_Marshal(&outCreation->t.creationData,  | 
646  | 2  |                          &buffer, &bufferSize);  | 
647  |  |    // Compute hash for creation field in public template  | 
648  | 2  |    creationDigest->t.size = CryptStartHash(nameHashAlg, &hashState);  | 
649  | 2  |    CryptUpdateDigest(&hashState, outCreation->t.size, creationBuffer);  | 
650  | 2  |    CryptCompleteHash2B(&hashState, &creationDigest->b);  | 
651  | 2  |    return;  | 
652  | 2  | }  | 
653  |  | //           GetSeedForKDF()  | 
654  |  | //  | 
655  |  | //      Get a seed for KDF. The KDF for encryption and HMAC key use the same seed. It returns a pointer to  | 
656  |  | //      the seed  | 
657  |  | //  | 
658  |  | TPM2B_SEED*  | 
659  |  | GetSeedForKDF(  | 
660  |  |     TPM_HANDLE           protectorHandle,          // IN: the protector handle  | 
661  |  |     TPM2B_SEED          *seedIn                    // IN: the optional input seed  | 
662  |  |     )  | 
663  | 0  | { | 
664  | 0  |     OBJECT                   *protector = NULL; // Pointer to the protector  | 
665  |  |     // Get seed for encryption key. Use input seed if provided.  | 
666  |  |     // Otherwise, using protector object's seedValue. TPM_RH_NULL is the only  | 
667  |  |     // exception that we may not have a loaded object as protector. In such a  | 
668  |  |     // case, use nullProof as seed.  | 
669  | 0  |     if(seedIn != NULL)  | 
670  | 0  |     { | 
671  | 0  |         return seedIn;  | 
672  | 0  |     }  | 
673  | 0  |     else  | 
674  | 0  |     { | 
675  | 0  |         if(protectorHandle == TPM_RH_NULL)  | 
676  | 0  |         { | 
677  | 0  |              return (TPM2B_SEED *) &gr.nullProof;  | 
678  | 0  |         }  | 
679  | 0  |         else  | 
680  | 0  |         { | 
681  | 0  |              protector = ObjectGet(protectorHandle);  | 
682  | 0  |              return (TPM2B_SEED *) &protector->sensitive.seedValue;  | 
683  | 0  |         }  | 
684  | 0  |     }  | 
685  | 0  | }  | 
686  |  | //  | 
687  |  | //  | 
688  |  | //           ProduceOuterWrap()  | 
689  |  | //  | 
690  |  | //      This function produce outer wrap for a buffer containing the sensitive data. It requires the sensitive data  | 
691  |  | //      being marshaled to the outerBuffer, with the leading bytes reserved for integrity hash. If iv is used, iv  | 
692  |  | //      space should be reserved at the beginning of the buffer. It assumes the sensitive data starts at address  | 
693  |  | //      (outerBuffer + integrity size {+ iv size}). This function performs: | 
694  |  | //      a) Add IV before sensitive area if required  | 
695  |  | //      b) encrypt sensitive data, if iv is required, encrypt by iv. otherwise, encrypted by a NULL iv  | 
696  |  | //      c) add HMAC integrity at the beginning of the buffer It returns the total size of blob with outer wrap  | 
697  |  | //  | 
698  |  | UINT16  | 
699  |  | ProduceOuterWrap(  | 
700  |  |     TPM_HANDLE           protector,          //   IN: The handle of the object that provides  | 
701  |  |                                              //       protection. For object, it is parent  | 
702  |  |                                              //       handle. For credential, it is the handle  | 
703  |  |                                              //       of encrypt object.  | 
704  |  |     TPM2B_NAME          *name,               //   IN: the name of the object  | 
705  |  |     TPM_ALG_ID           hashAlg,            //   IN: hash algorithm for outer wrap  | 
706  |  |     TPM2B_SEED          *seed,               //   IN: an external seed may be provided for  | 
707  |  |                                              //       duplication blob. For non duplication  | 
708  |  |                                              //       blob, this parameter should be NULL  | 
709  |  |     BOOL                 useIV,              //   IN: indicate if an IV is used  | 
710  |  |     UINT16               dataSize,           //   IN: the size of sensitive data, excluding the  | 
711  |  |                                              //       leading integrity buffer size or the  | 
712  |  |                                              //       optional iv size  | 
713  |  |     BYTE                *outerBuffer         //   IN/OUT: outer buffer with sensitive data in  | 
714  |  |                                        //     it  | 
715  |  |    )  | 
716  | 0  | { | 
717  | 0  |    TPM_ALG_ID         symAlg;  | 
718  | 0  |    UINT16             keyBits;  | 
719  | 0  |    TPM2B_SYM_KEY      symKey;  | 
720  | 0  |    TPM2B_IV           ivRNG;           // IV from RNG  | 
721  | 0  |    TPM2B_IV           *iv = NULL;  | 
722  | 0  |    UINT16             ivSize = 0;      // size of iv area, including the size field  | 
723  | 0  |    BYTE               *sensitiveData; // pointer to the sensitive data  | 
724  | 0  |    TPM2B_DIGEST       integrity;  | 
725  | 0  |    UINT16             integritySize;  | 
726  | 0  |    BYTE               *buffer;         // Auxiliary buffer pointer  | 
727  | 0  |    INT32              bufferSize;  | 
728  |  |    // Compute the beginning of sensitive data. The outer integrity should  | 
729  |  |    // always exist if this function function is called to make an outer wrap  | 
730  | 0  |    integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);  | 
731  | 0  |    sensitiveData = outerBuffer + integritySize;  | 
732  |  |    // If iv is used, adjust the pointer of sensitive data and add iv before it  | 
733  | 0  |    if(useIV)  | 
734  | 0  |    { | 
735  | 0  |        ivSize = GetIV2BSize(protector);  | 
736  |  |          // Generate IV from RNG. The iv data size should be the total IV area  | 
737  |  |          // size minus the size of size field  | 
738  | 0  |          ivRNG.t.size = ivSize - sizeof(UINT16);  | 
739  | 0  |          CryptGenerateRandom(ivRNG.t.size, ivRNG.t.buffer);  | 
740  |  |          // Marshal IV to buffer  | 
741  | 0  |          buffer = sensitiveData;  | 
742  | 0  |          bufferSize = sizeof(TPM2B_IV);  | 
743  | 0  |          TPM2B_IV_Marshal(&ivRNG, &buffer, &bufferSize);  | 
744  |  |          // adjust sensitive data starting after IV area  | 
745  | 0  |          sensitiveData += ivSize;  | 
746  |  |          // Use iv for encryption  | 
747  | 0  |          iv = &ivRNG;  | 
748  | 0  |    }  | 
749  |  |    // Compute symmetric key parameters for outer buffer encryption  | 
750  | 0  |    ComputeProtectionKeyParms(protector, hashAlg, name, seed,  | 
751  | 0  |                              &symAlg, &keyBits, &symKey);  | 
752  |  |    // Encrypt inner buffer in place  | 
753  | 0  |    CryptSymmetricEncrypt(sensitiveData, symAlg, keyBits,  | 
754  | 0  |                          TPM_ALG_CFB, symKey.t.buffer, iv, dataSize,  | 
755  | 0  |                          sensitiveData);  | 
756  |  |    // Compute outer integrity. Integrity computation includes the optional IV  | 
757  |  |    // area  | 
758  | 0  |    ComputeOuterIntegrity(name, protector, hashAlg, seed, dataSize + ivSize,  | 
759  | 0  |                          outerBuffer + integritySize, &integrity);  | 
760  |  |    // Add integrity at the beginning of outer buffer  | 
761  | 0  |    buffer = outerBuffer;  | 
762  | 0  |    bufferSize = sizeof(TPM2B_DIGEST);  | 
763  | 0  |    TPM2B_DIGEST_Marshal(&integrity, &buffer, &bufferSize);  | 
764  |  |    // return the total size in outer wrap  | 
765  | 0  |    return dataSize + integritySize + ivSize;  | 
766  | 0  | }  | 
767  |  | //  | 
768  |  | //  | 
769  |  | //  | 
770  |  | //           UnwrapOuter()  | 
771  |  | //  | 
772  |  | //      This function remove the outer wrap of a blob containing sensitive data This function performs:  | 
773  |  | //      a) check integrity of outer blob  | 
774  |  | //      b) decrypt outer blob  | 
775  |  | //  | 
776  |  | //      Error Returns                      Meaning  | 
777  |  | //  | 
778  |  | //      TPM_RC_INSUFFICIENT                error during sensitive data unmarshaling  | 
779  |  | //      TPM_RC_INTEGRITY                   sensitive data integrity is broken  | 
780  |  | //      TPM_RC_SIZE                        error during sensitive data unmarshaling  | 
781  |  | //      TPM_RC_VALUE                       IV size for CFB does not match the encryption algorithm block size  | 
782  |  | //  | 
783  |  | TPM_RC  | 
784  |  | UnwrapOuter(  | 
785  |  |    TPM_HANDLE           protector,             //   IN: The handle of the object that provides  | 
786  |  |                                                //       protection. For object, it is parent  | 
787  |  |                                                //       handle. For credential, it is the handle  | 
788  |  |                                                //       of encrypt object.  | 
789  |  |    TPM2B_NAME          *name,                  //   IN: the name of the object  | 
790  |  |    TPM_ALG_ID           hashAlg,               //   IN: hash algorithm for outer wrap  | 
791  |  |    TPM2B_SEED          *seed,                  //   IN: an external seed may be provided for  | 
792  |  |                                                //       duplication blob. For non duplication  | 
793  |  |                                                //       blob, this parameter should be NULL.  | 
794  |  |    BOOL                 useIV,                 //   IN: indicates if an IV is used  | 
795  |  |    UINT16               dataSize,              //   IN: size of sensitive data in outerBuffer,  | 
796  |  |                                                //       including the leading integrity buffer  | 
797  |  |                                                //       size, and an optional iv area  | 
798  |  |    BYTE                *outerBuffer            //   IN/OUT: sensitive data  | 
799  |  |    )  | 
800  | 0  | { | 
801  | 0  |    TPM_RC              result;  | 
802  | 0  |    TPM_ALG_ID          symAlg = TPM_ALG_NULL;  | 
803  | 0  |    TPM2B_SYM_KEY       symKey;  | 
804  | 0  |    UINT16              keyBits = 0;  | 
805  | 0  |    TPM2B_IV            ivIn;               // input IV retrieved from input buffer  | 
806  | 0  |    TPM2B_IV            *iv = NULL;  | 
807  | 0  |    BYTE                *sensitiveData;               // pointer to the sensitive data  | 
808  | 0  |    TPM2B_DIGEST        integrityToCompare;  | 
809  | 0  |    TPM2B_DIGEST        integrity;  | 
810  | 0  |    INT32               size;  | 
811  |  |    // Unmarshal integrity  | 
812  | 0  |    sensitiveData = outerBuffer;  | 
813  | 0  |    size = (INT32) dataSize;  | 
814  | 0  |    result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size);  | 
815  | 0  |    if(result == TPM_RC_SUCCESS)  | 
816  | 0  |    { | 
817  |  |        // Compute integrity to compare  | 
818  | 0  |        ComputeOuterIntegrity(name, protector, hashAlg, seed,  | 
819  | 0  |                              (UINT16) size, sensitiveData,  | 
820  | 0  |                              &integrityToCompare);  | 
821  |  |          // Compare outer blob integrity  | 
822  | 0  |          if(!Memory2BEqual(&integrity.b, &integrityToCompare.b))  | 
823  | 0  |              return TPM_RC_INTEGRITY;  | 
824  |  |          // Get the symmetric algorithm parameters used for encryption  | 
825  | 0  |          ComputeProtectionKeyParms(protector, hashAlg, name, seed,  | 
826  | 0  |                                           &symAlg, &keyBits, &symKey);  | 
827  |  |          // Retrieve IV if it is used  | 
828  | 0  |          if(useIV)  | 
829  | 0  |          { | 
830  | 0  |              result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size);  | 
831  | 0  |              if(result == TPM_RC_SUCCESS)  | 
832  | 0  |              { | 
833  |  |                  // The input iv size for CFB must match the encryption algorithm  | 
834  |  |                  // block size  | 
835  | 0  |                  if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits))  | 
836  | 0  |                      result = TPM_RC_VALUE;  | 
837  | 0  |                  else  | 
838  | 0  |                      iv = &ivIn;  | 
839  | 0  |              }  | 
840  | 0  |          }  | 
841  | 0  |     }  | 
842  |  |     // If no errors, decrypt private in place  | 
843  | 0  |     if(result == TPM_RC_SUCCESS)  | 
844  | 0  |         CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits,  | 
845  | 0  |                               TPM_ALG_CFB, symKey.t.buffer, iv,  | 
846  | 0  |                               (UINT16) size, sensitiveData);  | 
847  | 0  |     return result;  | 
848  | 0  | }  | 
849  |  | //  | 
850  |  | //  | 
851  |  | //           SensitiveToPrivate()  | 
852  |  | //  | 
853  |  | //      This function prepare the private blob for off the chip storage The operations in this function:  | 
854  |  | //      a) marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE  | 
855  |  | //      b) apply encryption to the sensitive area.  | 
856  |  | //      c) apply outer integrity computation.  | 
857  |  | //  | 
858  |  | void  | 
859  |  | SensitiveToPrivate(  | 
860  |  |     TPMT_SENSITIVE      *sensitive,         //   IN: sensitive structure  | 
861  |  |     TPM2B_NAME          *name,              //   IN: the name of the object  | 
862  |  |     TPM_HANDLE           parentHandle,      //   IN: The parent's handle  | 
863  |  |     TPM_ALG_ID           nameAlg,           //   IN: hash algorithm in public area. This  | 
864  |  |                                             //       parameter is used when parentHandle is  | 
865  |  |                                             //       NULL, in which case the object is  | 
866  |  |                                             //       temporary.  | 
867  |  |     TPM2B_PRIVATE       *outPrivate         //   OUT: output private structure  | 
868  |  |     )  | 
869  | 0  | { | 
870  | 0  |     BYTE                     *buffer;                  //   Auxiliary buffer pointer  | 
871  | 0  |     INT32                    bufferSize;  | 
872  | 0  |     BYTE                     *sensitiveData;           //   pointer to the sensitive data  | 
873  | 0  |     UINT16                   dataSize;                 //   data blob size  | 
874  | 0  |     TPMI_ALG_HASH            hashAlg;                  //   hash algorithm for integrity  | 
875  | 0  |     UINT16                   integritySize;  | 
876  | 0  |     UINT16                   ivSize;  | 
877  | 0  |     pAssert(name != NULL && name->t.size != 0);  | 
878  |  |     // Find the hash algorithm for integrity computation  | 
879  | 0  |     if(parentHandle == TPM_RH_NULL)  | 
880  | 0  |     { | 
881  |  |         // For Temporary Object, using self name algorithm  | 
882  | 0  |         hashAlg = nameAlg;  | 
883  | 0  |     }  | 
884  | 0  |     else  | 
885  | 0  |    { | 
886  |  |          // Otherwise, using parent's name algorithm  | 
887  | 0  |          hashAlg = ObjectGetNameAlg(parentHandle);  | 
888  | 0  |    }  | 
889  |  |    // Starting of sensitive data without wrappers  | 
890  | 0  |    sensitiveData = outPrivate->t.buffer;  | 
891  |  |    // Compute the integrity size  | 
892  | 0  |    integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);  | 
893  |  |    // Reserve space for integrity  | 
894  | 0  |    sensitiveData += integritySize;  | 
895  |  |    // Get iv size  | 
896  | 0  |    ivSize = GetIV2BSize(parentHandle);  | 
897  |  |    // Reserve space for iv  | 
898  | 0  |    sensitiveData += ivSize;  | 
899  |  |    // Marshal sensitive area, leaving the leading 2 bytes for size  | 
900  | 0  |    buffer = sensitiveData + sizeof(UINT16);  | 
901  | 0  |    bufferSize = sizeof(TPMT_SENSITIVE);  | 
902  | 0  |    dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, &bufferSize);  | 
903  |  |    // Adding size before the data area  | 
904  | 0  |    buffer = sensitiveData;  | 
905  | 0  |    bufferSize = sizeof(UINT16);  | 
906  | 0  |    UINT16_Marshal(&dataSize, &buffer, &bufferSize);  | 
907  |  |    // Adjust the dataSize to include the size field  | 
908  | 0  |    dataSize += sizeof(UINT16);  | 
909  |  |    // Adjust the pointer to inner buffer including the iv  | 
910  | 0  |    sensitiveData = outPrivate->t.buffer + ivSize;  | 
911  |  |    //Produce outer wrap, including encryption and HMAC  | 
912  | 0  |    outPrivate->t.size = ProduceOuterWrap(parentHandle, name, hashAlg, NULL,  | 
913  | 0  |                                          TRUE, dataSize, outPrivate->t.buffer);  | 
914  | 0  |    return;  | 
915  | 0  | }  | 
916  |  | //  | 
917  |  | //  | 
918  |  | //           PrivateToSensitive()  | 
919  |  | //  | 
920  |  | //      Unwrap a input private area. Check the integrity, decrypt and retrieve data to a sensitive structure. The  | 
921  |  | //      operations in this function:  | 
922  |  | //      a) check the integrity HMAC of the input private area  | 
923  |  | //      b) decrypt the private buffer  | 
924  |  | //      c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE  | 
925  |  | //  | 
926  |  | //      Error Returns                   Meaning  | 
927  |  | //  | 
928  |  | //      TPM_RC_INTEGRITY                if the private area integrity is bad  | 
929  |  | //      TPM_RC_SENSITIVE                unmarshal errors while unmarshaling TPMS_ENCRYPT from input  | 
930  |  | //                                      private  | 
931  |  | //      TPM_RC_VALUE                    outer wrapper does not have an iV of the correct size  | 
932  |  | //  | 
933  |  | TPM_RC  | 
934  |  | PrivateToSensitive(  | 
935  |  |    TPM2B_PRIVATE       *inPrivate,          // IN: input private structure  | 
936  |  |    TPM2B_NAME          *name,               // IN: the name of the object  | 
937  |  |    TPM_HANDLE          parentHandle,    // IN: The parent's handle  | 
938  |  |    TPM_ALG_ID          nameAlg,         // IN: hash algorithm in public area. It is  | 
939  |  |                                         //     passed separately because we only pass  | 
940  |  |                                         //     name, rather than the whole public area  | 
941  |  |                                         //     of the object. This parameter is used in  | 
942  |  |                                         //     the following two cases: 1. primary  | 
943  |  |                                         //     objects. 2. duplication blob with inner  | 
944  |  |                                         //     wrap. In other cases, this parameter  | 
945  |  |                                         //     will be ignored  | 
946  |  |    TPMT_SENSITIVE     *sensitive        // OUT: sensitive structure  | 
947  |  |    )  | 
948  | 0  | { | 
949  | 0  |    TPM_RC             result;  | 
950  | 0  |    BYTE               *buffer;  | 
951  | 0  |    INT32              size;  | 
952  | 0  |    BYTE               *sensitiveData; // pointer to the sensitive data  | 
953  | 0  |    UINT16             dataSize;  | 
954  | 0  |    UINT16             dataSizeInput;  | 
955  | 0  |    TPMI_ALG_HASH      hashAlg;        // hash algorithm for integrity  | 
956  | 0  |    OBJECT             *parent = NULL;  | 
957  | 0  |    UINT16             integritySize;  | 
958  | 0  |    UINT16             ivSize;  | 
959  |  |    // Make sure that name is provided  | 
960  | 0  |    pAssert(name != NULL && name->t.size != 0);  | 
961  |  |    // Find the hash algorithm for integrity computation  | 
962  | 0  |    if(parentHandle == TPM_RH_NULL)  | 
963  | 0  |    { | 
964  |  |        // For Temporary Object, using self name algorithm  | 
965  | 0  |        hashAlg = nameAlg;  | 
966  | 0  |    }  | 
967  | 0  |    else  | 
968  | 0  |    { | 
969  |  |        // Otherwise, using parent's name algorithm  | 
970  | 0  |        hashAlg = ObjectGetNameAlg(parentHandle);  | 
971  | 0  |    }  | 
972  |  |    // unwrap outer  | 
973  | 0  |    result = UnwrapOuter(parentHandle, name, hashAlg, NULL, TRUE,  | 
974  | 0  |                         inPrivate->t.size, inPrivate->t.buffer);  | 
975  | 0  |    if(result != TPM_RC_SUCCESS)  | 
976  | 0  |        return result;  | 
977  |  |    // Compute the inner integrity size.  | 
978  | 0  |    integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);  | 
979  |  |    // Get iv size  | 
980  | 0  |    ivSize = GetIV2BSize(parentHandle);  | 
981  |  |    // The starting of sensitive data and data size without outer wrapper  | 
982  | 0  |    sensitiveData = inPrivate->t.buffer + integritySize + ivSize;  | 
983  | 0  |    dataSize = inPrivate->t.size - integritySize - ivSize;  | 
984  |  |    // Unmarshal input data size  | 
985  | 0  |    buffer = sensitiveData;  | 
986  | 0  |    size = (INT32) dataSize;  | 
987  | 0  |    result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size);  | 
988  | 0  |    if(result == TPM_RC_SUCCESS)  | 
989  | 0  |    { | 
990  | 0  |        if((dataSizeInput + sizeof(UINT16)) != dataSize)  | 
991  | 0  |             result = TPM_RC_SENSITIVE;  | 
992  | 0  |        else  | 
993  | 0  |        { | 
994  |  |               // Unmarshal sensitive buffer to sensitive structure  | 
995  | 0  |               result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size);  | 
996  | 0  |               if(result != TPM_RC_SUCCESS || size != 0)  | 
997  | 0  |               { | 
998  | 0  |                   pAssert(    (parent == NULL)  | 
999  | 0  |                            || parent->publicArea.objectAttributes.fixedTPM == CLEAR);  | 
1000  | 0  |                   result = TPM_RC_SENSITIVE;  | 
1001  | 0  |               }  | 
1002  | 0  |               else  | 
1003  | 0  |               { | 
1004  |  |                   // Always remove trailing zeros at load so that it is not necessary  | 
1005  |  |                   // to check  | 
1006  |  |                   // each time auth is checked.  | 
1007  | 0  |                   MemoryRemoveTrailingZeros(&(sensitive->authValue));  | 
1008  | 0  |               }  | 
1009  | 0  |         }  | 
1010  | 0  |     }  | 
1011  | 0  |     return result;  | 
1012  | 0  | }  | 
1013  |  | //  | 
1014  |  | //  | 
1015  |  | //          SensitiveToDuplicate()  | 
1016  |  | //  | 
1017  |  | //      This function prepare the duplication blob from the sensitive area. The operations in this function:  | 
1018  |  | //      a) marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE  | 
1019  |  | //      b) apply inner wrap to the sensitive area if required  | 
1020  |  | //      c) apply outer wrap if required  | 
1021  |  | //  | 
1022  |  | void  | 
1023  |  | SensitiveToDuplicate(  | 
1024  |  |     TPMT_SENSITIVE                *sensitive,          //   IN: sensitive structure  | 
1025  |  |     TPM2B_NAME                    *name,               //   IN: the name of the object  | 
1026  |  |     TPM_HANDLE                     parentHandle,       //   IN: The new parent's handle  | 
1027  |  |     TPM_ALG_ID                     nameAlg,            //   IN: hash algorithm in public area. It  | 
1028  |  |                                                        //       is passed separately because we  | 
1029  |  |                                                        //       only pass name, rather than the  | 
1030  |  |                                                        //       whole public area of the object.  | 
1031  |  |     TPM2B_SEED                    *seed,               //   IN: the external seed. If external  | 
1032  |  |                                                        //       seed is provided with size of 0,  | 
1033  |  |                                                        //       no outer wrap should be applied  | 
1034  |  |                                                        //       to duplication blob.  | 
1035  |  |     TPMT_SYM_DEF_OBJECT           *symDef,             //   IN: Symmetric key definition. If the  | 
1036  |  |                                                        //       symmetric key algorithm is NULL,  | 
1037  |  |                                                        //       no inner wrap should be applied.  | 
1038  |  |     TPM2B_DATA                    *innerSymKey,        //   IN/OUT: a symmetric key may be  | 
1039  |  |                                                        //       provided to encrypt the inner  | 
1040  |  |                                                        //       wrap of a duplication blob. May  | 
1041  |  |                                                        //       be generated here if needed.  | 
1042  |  |     TPM2B_PRIVATE                 *outPrivate          //   OUT: output private structure  | 
1043  |  |     )  | 
1044  | 0  | { | 
1045  | 0  |     BYTE                *buffer;        // Auxiliary buffer pointer  | 
1046  | 0  |     INT32               bufferSize;  | 
1047  | 0  |     BYTE                *sensitiveData; // pointer to the sensitive data  | 
1048  | 0  |     TPMI_ALG_HASH       outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap  | 
1049  | 0  |     TPMI_ALG_HASH       innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap  | 
1050  | 0  |     UINT16              dataSize;       // data blob size  | 
1051  | 0  |     BOOL                doInnerWrap = FALSE;  | 
1052  | 0  |     BOOL                doOuterWrap = FALSE;  | 
1053  |  |     // Make sure that name is provided  | 
1054  | 0  |     pAssert(name != NULL && name->t.size != 0);  | 
1055  |  |     // Make sure symDef and innerSymKey are not NULL  | 
1056  | 0  |    pAssert(symDef != NULL && innerSymKey != NULL);  | 
1057  |  |    // Starting of sensitive data without wrappers  | 
1058  | 0  |    sensitiveData = outPrivate->t.buffer;  | 
1059  |  |    // Find out if inner wrap is required  | 
1060  | 0  |    if(symDef->algorithm != TPM_ALG_NULL)  | 
1061  | 0  |    { | 
1062  | 0  |        doInnerWrap = TRUE;  | 
1063  |  |        // Use self nameAlg as inner hash algorithm  | 
1064  | 0  |        innerHash = nameAlg;  | 
1065  |  |        // Adjust sensitive data pointer  | 
1066  | 0  |        sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash);  | 
1067  | 0  |    }  | 
1068  |  |    // Find out if outer wrap is required  | 
1069  | 0  |    if(seed->t.size != 0)  | 
1070  | 0  |    { | 
1071  | 0  |        doOuterWrap = TRUE;  | 
1072  |  |        // Use parent nameAlg as outer hash algorithm  | 
1073  | 0  |        outerHash = ObjectGetNameAlg(parentHandle);  | 
1074  |  |        // Adjust sensitive data pointer  | 
1075  | 0  |        sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash);  | 
1076  | 0  |    }  | 
1077  |  |    // Marshal sensitive area, leaving the leading 2 bytes for size  | 
1078  | 0  |    buffer = sensitiveData + sizeof(UINT16);  | 
1079  | 0  |    bufferSize = sizeof(TPMT_SENSITIVE);  | 
1080  | 0  |    dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, &bufferSize);  | 
1081  |  |    // Adding size before the data area  | 
1082  | 0  |    buffer = sensitiveData;  | 
1083  | 0  |    bufferSize = sizeof(UINT16);  | 
1084  | 0  |    UINT16_Marshal(&dataSize, &buffer, &bufferSize);  | 
1085  |  |    // Adjust the dataSize to include the size field  | 
1086  | 0  |    dataSize += sizeof(UINT16);  | 
1087  |  |    // Apply inner wrap for duplication blob. It includes both integrity and  | 
1088  |  |    // encryption  | 
1089  | 0  |    if(doInnerWrap)  | 
1090  | 0  |    { | 
1091  | 0  |        BYTE             *innerBuffer = NULL;  | 
1092  | 0  |        BOOL             symKeyInput = TRUE;  | 
1093  | 0  |        innerBuffer = outPrivate->t.buffer;  | 
1094  |  |        // Skip outer integrity space  | 
1095  | 0  |        if(doOuterWrap)  | 
1096  | 0  |             innerBuffer += sizeof(UINT16) + CryptGetHashDigestSize(outerHash);  | 
1097  | 0  |        dataSize = ProduceInnerIntegrity(name, innerHash, dataSize,  | 
1098  | 0  |                                          innerBuffer);  | 
1099  |  |         // Generate inner encryption key if needed  | 
1100  | 0  |         if(innerSymKey->t.size == 0)  | 
1101  | 0  |         { | 
1102  | 0  |             innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8;  | 
1103  | 0  |             CryptGenerateRandom(innerSymKey->t.size, innerSymKey->t.buffer);  | 
1104  |  |              // TPM generates symmetric encryption.   Set the flag to FALSE  | 
1105  | 0  |              symKeyInput = FALSE;  | 
1106  | 0  |         }  | 
1107  | 0  |         else  | 
1108  | 0  |         { | 
1109  |  |              // assume the input key size should matches the symmetric definition  | 
1110  | 0  |              pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8);  | 
1111  | 0  |         }  | 
1112  |  |         // Encrypt inner buffer in place  | 
1113  | 0  |           CryptSymmetricEncrypt(innerBuffer, symDef->algorithm,  | 
1114  | 0  |                                 symDef->keyBits.sym, TPM_ALG_CFB,  | 
1115  | 0  |                                 innerSymKey->t.buffer, NULL, dataSize,  | 
1116  | 0  |                                 innerBuffer);  | 
1117  |  |           // If the symmetric encryption key is imported, clear the buffer for  | 
1118  |  |           // output  | 
1119  | 0  |           if(symKeyInput)  | 
1120  | 0  |               innerSymKey->t.size = 0;  | 
1121  | 0  |    }  | 
1122  |  |    // Apply outer wrap for duplication blob. It includes both integrity and  | 
1123  |  |    // encryption  | 
1124  | 0  |    if(doOuterWrap)  | 
1125  | 0  |    { | 
1126  | 0  |        dataSize = ProduceOuterWrap(parentHandle, name, outerHash, seed, FALSE,  | 
1127  | 0  |                                    dataSize, outPrivate->t.buffer);  | 
1128  | 0  |    }  | 
1129  |  |    // Data size for output  | 
1130  | 0  |    outPrivate->t.size = dataSize;  | 
1131  | 0  |    return;  | 
1132  | 0  | }  | 
1133  |  | //  | 
1134  |  | //  | 
1135  |  | //           DuplicateToSensitive()  | 
1136  |  | //  | 
1137  |  | //       Unwrap a duplication blob. Check the integrity, decrypt and retrieve data to a sensitive structure. The  | 
1138  |  | //       operations in this function:  | 
1139  |  | //       a) check the integrity HMAC of the input private area  | 
1140  |  | //       b) decrypt the private buffer  | 
1141  |  | //       c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE  | 
1142  |  | //  | 
1143  |  | //       Error Returns                   Meaning  | 
1144  |  | //  | 
1145  |  | //       TPM_RC_INSUFFICIENT             unmarshaling sensitive data from inPrivate failed  | 
1146  |  | //       TPM_RC_INTEGRITY                inPrivate data integrity is broken  | 
1147  |  | //       TPM_RC_SIZE                     unmarshaling sensitive data from inPrivate failed  | 
1148  |  | //  | 
1149  |  | TPM_RC  | 
1150  |  | DuplicateToSensitive(  | 
1151  |  |    TPM2B_PRIVATE                 *inPrivate,           //   IN: input private structure  | 
1152  |  |    TPM2B_NAME                    *name,                //   IN: the name of the object  | 
1153  |  |    TPM_HANDLE                     parentHandle,        //   IN: The parent's handle  | 
1154  |  |    TPM_ALG_ID                     nameAlg,             //   IN: hash algorithm in public area.  | 
1155  |  |    TPM2B_SEED                    *seed,                //   IN: an external seed may be provided.  | 
1156  |  |                                                        //       If external seed is provided with  | 
1157  |  |                                                        //       size of 0, no outer wrap is  | 
1158  |  |                                                        //       applied  | 
1159  |  |    TPMT_SYM_DEF_OBJECT           *symDef,              //   IN: Symmetric key definition. If the  | 
1160  |  |                                                        //       symmetric key algorithm is NULL,  | 
1161  |  |                                                        //       no inner wrap is applied  | 
1162  |  |    TPM2B_DATA                    *innerSymKey,         //   IN: a symmetric key may be provided  | 
1163  |  |                                                        //       to decrypt the inner wrap of a  | 
1164  |  |                                                        //       duplication blob.  | 
1165  |  |    TPMT_SENSITIVE                *sensitive            //   OUT: sensitive structure  | 
1166  |  |    )  | 
1167  | 0  | { | 
1168  | 0  |    TPM_RC              result;  | 
1169  | 0  |    BYTE               *buffer;  | 
1170  | 0  |    INT32              size;  | 
1171  | 0  |    BYTE               *sensitiveData; // pointer to the sensitive data  | 
1172  | 0  |    UINT16             dataSize;  | 
1173  | 0  |    UINT16             dataSizeInput;  | 
1174  |  |    // Make sure that name is provided  | 
1175  | 0  |    pAssert(name != NULL && name->t.size != 0);  | 
1176  |  |    // Make sure symDef and innerSymKey are not NULL  | 
1177  | 0  |    pAssert(symDef != NULL && innerSymKey != NULL);  | 
1178  |  |    // Starting of sensitive data  | 
1179  | 0  |    sensitiveData = inPrivate->t.buffer;  | 
1180  | 0  |    dataSize = inPrivate->t.size;  | 
1181  |  |    // Find out if outer wrap is applied  | 
1182  | 0  |    if(seed->t.size != 0)  | 
1183  | 0  |    { | 
1184  | 0  |        TPMI_ALG_HASH   outerHash = TPM_ALG_NULL;  | 
1185  |  |         // Use parent nameAlg as outer hash algorithm  | 
1186  | 0  |         outerHash = ObjectGetNameAlg(parentHandle);  | 
1187  | 0  |         result = UnwrapOuter(parentHandle, name, outerHash, seed, FALSE,  | 
1188  | 0  |                              dataSize, sensitiveData);  | 
1189  | 0  |         if(result != TPM_RC_SUCCESS)  | 
1190  | 0  |             return result;  | 
1191  |  |         // Adjust sensitive data pointer and size  | 
1192  | 0  |         sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash);  | 
1193  | 0  |         dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(outerHash);  | 
1194  | 0  |    }  | 
1195  |  |    // Find out if inner wrap is applied  | 
1196  | 0  |    if(symDef->algorithm != TPM_ALG_NULL)  | 
1197  | 0  |    { | 
1198  | 0  |        TPMI_ALG_HASH   innerHash = TPM_ALG_NULL;  | 
1199  |  |         // assume the input key size should matches the symmetric definition  | 
1200  | 0  |         pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8);  | 
1201  |  |         // Decrypt inner buffer in place  | 
1202  | 0  |         CryptSymmetricDecrypt(sensitiveData, symDef->algorithm,  | 
1203  | 0  |                               symDef->keyBits.sym, TPM_ALG_CFB,  | 
1204  | 0  |                               innerSymKey->t.buffer, NULL, dataSize,  | 
1205  | 0  |                               sensitiveData);  | 
1206  |  |         // Use self nameAlg as inner hash algorithm  | 
1207  | 0  |         innerHash = nameAlg;  | 
1208  |  |         // Check inner integrity  | 
1209  | 0  |         result = CheckInnerIntegrity(name, innerHash, dataSize, sensitiveData);  | 
1210  | 0  |         if(result != TPM_RC_SUCCESS)  | 
1211  | 0  |             return result;  | 
1212  |  |         // Adjust sensitive data pointer and size  | 
1213  | 0  |         sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash);  | 
1214  | 0  |         dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(innerHash);  | 
1215  | 0  |    }  | 
1216  |  |    // Unmarshal input data size  | 
1217  | 0  |    buffer = sensitiveData;  | 
1218  | 0  |    size = (INT32) dataSize;  | 
1219  | 0  |    result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size);  | 
1220  | 0  |    if(result == TPM_RC_SUCCESS)  | 
1221  | 0  |    { | 
1222  | 0  |        if((dataSizeInput + sizeof(UINT16)) != dataSize)  | 
1223  | 0  |               result = TPM_RC_SIZE;  | 
1224  | 0  |           else  | 
1225  | 0  |           { | 
1226  |  |               // Unmarshal sensitive buffer to sensitive structure  | 
1227  | 0  |               result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size);  | 
1228  |  |               // if the results is OK make sure that all the data was unmarshaled  | 
1229  | 0  |               if(result == TPM_RC_SUCCESS && size != 0)  | 
1230  | 0  |                   result = TPM_RC_SIZE;  | 
1231  | 0  |        }  | 
1232  | 0  |    }  | 
1233  |  |    // Always remove trailing zeros at load so that it is not necessary to check  | 
1234  |  |    // each time auth is checked.  | 
1235  | 0  |    if(result == TPM_RC_SUCCESS)  | 
1236  | 0  |        MemoryRemoveTrailingZeros(&(sensitive->authValue));  | 
1237  | 0  |    return result;  | 
1238  | 0  | }  | 
1239  |  | //  | 
1240  |  | //  | 
1241  |  | //           SecretToCredential()  | 
1242  |  | //  | 
1243  |  | //       This function prepare the credential blob from a secret (a TPM2B_DIGEST) The operations in this  | 
1244  |  | //       function:  | 
1245  |  | //       a) marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT  | 
1246  |  | //       b) encrypt the private buffer, excluding the leading integrity HMAC area  | 
1247  |  | //       c) compute integrity HMAC and append to the beginning of the buffer.  | 
1248  |  | //       d) Set the total size of TPM2B_ID_OBJECT buffer  | 
1249  |  | //  | 
1250  |  | void  | 
1251  |  | SecretToCredential(  | 
1252  |  |    TPM2B_DIGEST              *secret,          //   IN: secret information  | 
1253  |  |    TPM2B_NAME                *name,            //   IN: the name of the object  | 
1254  |  |    TPM2B_SEED                *seed,            //   IN: an external seed.  | 
1255  |  |    TPM_HANDLE                 protector,       //   IN: The protector's handle  | 
1256  |  |    TPM2B_ID_OBJECT           *outIDObject      //   OUT: output credential  | 
1257  |  |    )  | 
1258  | 0  | { | 
1259  | 0  |    BYTE                      *buffer;          //   Auxiliary buffer pointer  | 
1260  | 0  |    INT32                      bufferSize;  | 
1261  | 0  |    BYTE                      *sensitiveData;   //   pointer to the sensitive data  | 
1262  | 0  |    TPMI_ALG_HASH              outerHash;       //   The hash algorithm for outer wrap  | 
1263  | 0  |    UINT16                     dataSize;        //   data blob size  | 
1264  | 0  |    pAssert(secret != NULL && outIDObject != NULL);  | 
1265  |  |    // use protector's name algorithm as outer hash  | 
1266  | 0  |    outerHash = ObjectGetNameAlg(protector);  | 
1267  |  |    // Marshal secret area to credential buffer, leave space for integrity  | 
1268  | 0  |    sensitiveData = outIDObject->t.credential  | 
1269  | 0  |                    + sizeof(UINT16) + CryptGetHashDigestSize(outerHash);  | 
1270  |  |    // Marshal secret area  | 
1271  | 0  |    buffer = sensitiveData;  | 
1272  | 0  |    bufferSize = sizeof(TPM2B_DIGEST);  | 
1273  | 0  |    dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, &bufferSize);  | 
1274  |  |    // Apply outer wrap  | 
1275  | 0  |    outIDObject->t.size = ProduceOuterWrap(protector,  | 
1276  | 0  |                                           name,  | 
1277  | 0  |                                           outerHash,  | 
1278  | 0  |                                           seed,  | 
1279  | 0  |                                           FALSE,  | 
1280  | 0  |                                           dataSize,  | 
1281  | 0  |                                           outIDObject->t.credential);  | 
1282  | 0  |    return;  | 
1283  | 0  | }  | 
1284  |  | //  | 
1285  |  | //  | 
1286  |  | //            CredentialToSecret()  | 
1287  |  | //  | 
1288  |  | //       Unwrap a credential. Check the integrity, decrypt and retrieve data to a TPM2B_DIGEST structure. The  | 
1289  |  | //       operations in this function:  | 
1290  |  | //       a) check the integrity HMAC of the input credential area  | 
1291  |  | //       b) decrypt the credential buffer  | 
1292  |  | //       c) unmarshal TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST  | 
1293  |  | //  | 
1294  |  | //       Error Returns                      Meaning  | 
1295  |  | //  | 
1296  |  | //       TPM_RC_INSUFFICIENT                error during credential unmarshaling  | 
1297  |  | //       TPM_RC_INTEGRITY                   credential integrity is broken  | 
1298  |  | //       TPM_RC_SIZE                        error during credential unmarshaling  | 
1299  |  | //       TPM_RC_VALUE                       IV size does not match the encryption algorithm block size  | 
1300  |  | //  | 
1301  |  | TPM_RC  | 
1302  |  | CredentialToSecret(  | 
1303  |  |    TPM2B_ID_OBJECT          *inIDObject,             //   IN: input credential blob  | 
1304  |  |    TPM2B_NAME               *name,                   //   IN: the name of the object  | 
1305  |  |    TPM2B_SEED               *seed,                   //   IN: an external seed.  | 
1306  |  |    TPM_HANDLE                protector,              //   IN: The protector's handle  | 
1307  |  |    TPM2B_DIGEST             *secret                  //   OUT: secret information  | 
1308  |  |    )  | 
1309  | 0  | { | 
1310  | 0  |    TPM_RC                           result;  | 
1311  | 0  |    BYTE                            *buffer;  | 
1312  | 0  |    INT32                            size;  | 
1313  | 0  |    TPMI_ALG_HASH                    outerHash;     // The hash algorithm for outer wrap  | 
1314  | 0  |    BYTE                            *sensitiveData; // pointer to the sensitive data  | 
1315  | 0  |    UINT16                           dataSize;  | 
1316  |  |    // use protector's name algorithm as outer hash  | 
1317  | 0  |    outerHash = ObjectGetNameAlg(protector);  | 
1318  |  |    // Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point  | 
1319  | 0  |    result = UnwrapOuter(protector, name, outerHash, seed, FALSE,  | 
1320  | 0  |                         inIDObject->t.size, inIDObject->t.credential);  | 
1321  | 0  |    if(result == TPM_RC_SUCCESS)  | 
1322  | 0  |    { | 
1323  |  |        // Compute the beginning of sensitive data  | 
1324  | 0  |        sensitiveData = inIDObject->t.credential  | 
1325  | 0  |                        + sizeof(UINT16) + CryptGetHashDigestSize(outerHash);  | 
1326  | 0  |        dataSize = inIDObject->t.size  | 
1327  | 0  |                   - (sizeof(UINT16) + CryptGetHashDigestSize(outerHash));  | 
1328  |  |           // Unmarshal secret buffer to TPM2B_DIGEST structure  | 
1329  | 0  |           buffer = sensitiveData;  | 
1330  | 0  |           size = (INT32) dataSize;  | 
1331  | 0  |           result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size);  | 
1332  |  |           // If there were no other unmarshaling errors, make sure that the  | 
1333  |  |           // expected amount of data was recovered  | 
1334  | 0  |           if(result == TPM_RC_SUCCESS && size != 0)  | 
1335  | 0  |               return TPM_RC_SIZE;  | 
1336  | 0  |    }  | 
1337  | 0  |    return result;  | 
1338  | 0  | }  |