1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 3: Commands
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7 
8 #include "InternalRoutines.h"
9 #include "Rewrap_fp.h"
10 #include "Object_spt_fp.h"
11 //
12 //
13 //     Error Returns                 Meaning
14 //
15 //     TPM_RC_ATTRIBUTES             newParent is not a decryption key
16 //     TPM_RC_HANDLE                 oldParent does not consistent with inSymSeed
17 //     TPM_RC_INTEGRITY              the integrity check of inDuplicate failed
18 //     TPM_RC_KEY                    for an ECC key, the public key is not on the curve of the curve ID
19 //     TPM_RC_KEY_SIZE               the decrypted input symmetric key size does not matches the
20 //                                   symmetric algorithm key size of oldParent
21 //     TPM_RC_TYPE                   oldParent is not a storage key, or 'newParent is not a storage key
22 //     TPM_RC_VALUE                  for an 'oldParent; RSA key, the data to be decrypted is greater than
23 //                                   the public exponent
24 //     Unmarshal errors              errors during unmarshaling the input encrypted buffer to a ECC public
25 //                                   key, or unmarshal the private buffer to sensitive
26 //
27 TPM_RC
TPM2_Rewrap(Rewrap_In * in,Rewrap_Out * out)28 TPM2_Rewrap(
29    Rewrap_In         *in,             // IN: input parameter list
30    Rewrap_Out        *out             // OUT: output parameter list
31    )
32 {
33    TPM_RC                   result = TPM_RC_SUCCESS;
34    OBJECT                   *oldParent;
35    TPM2B_DATA               data;               // symmetric key
36    UINT16                   hashSize = 0;
37    TPM2B_PRIVATE            privateBlob;        // A temporary private blob
38                                                 // to transit between old
39                                                 // and new wrappers
40 
41 // Input Validation
42 
43    if((in->inSymSeed.t.size == 0 && in->oldParent != TPM_RH_NULL)
44            || (in->inSymSeed.t.size != 0 && in->oldParent == TPM_RH_NULL))
45        return TPM_RC_HANDLE + RC_Rewrap_oldParent;
46 
47    if(in->oldParent != TPM_RH_NULL)
48    {
49        // Get old parent pointer
50        oldParent = ObjectGet(in->oldParent);
51 
52          // old parent key must be a storage object
53          if(!ObjectIsStorage(in->oldParent))
54              return TPM_RC_TYPE + RC_Rewrap_oldParent;
55 
56          // Decrypt input secret data via asymmetric decryption. A
57          // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
58          // point
59          result = CryptSecretDecrypt(in->oldParent, NULL,
60                                      "DUPLICATE", &in->inSymSeed, &data);
61          if(result != TPM_RC_SUCCESS)
62              return TPM_RC_VALUE + RC_Rewrap_inSymSeed;
63 
64        // Unwrap Outer
65        result = UnwrapOuter(in->oldParent, &in->name,
66                             oldParent->publicArea.nameAlg, (TPM2B_SEED *) &data,
67                             FALSE,
68                             in->inDuplicate.t.size, in->inDuplicate.t.buffer);
69        if(result != TPM_RC_SUCCESS)
70            return RcSafeAddToResult(result, RC_Rewrap_inDuplicate);
71 
72        // Copy unwrapped data to temporary variable, remove the integrity field
73        hashSize = sizeof(UINT16) +
74                   CryptGetHashDigestSize(oldParent->publicArea.nameAlg);
75        privateBlob.t.size = in->inDuplicate.t.size - hashSize;
76        MemoryCopy(privateBlob.t.buffer, in->inDuplicate.t.buffer + hashSize,
77                   privateBlob.t.size, sizeof(privateBlob.t.buffer));
78    }
79    else
80    {
81        // No outer wrap from input blob.   Direct copy.
82        privateBlob = in->inDuplicate;
83    }
84 
85    if(in->newParent != TPM_RH_NULL)
86    {
87        OBJECT          *newParent;
88        newParent = ObjectGet(in->newParent);
89 
90        // New parent must be a storage object
91        if(!ObjectIsStorage(in->newParent))
92            return TPM_RC_TYPE + RC_Rewrap_newParent;
93 
94        // Make new encrypt key and its associated secret structure. A
95        // TPM_RC_VALUE error may be returned at this point if RSA algorithm is
96        // enabled in TPM
97        out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
98        result = CryptSecretEncrypt(in->newParent,
99                                    "DUPLICATE", &data, &out->outSymSeed);
100        if(result != TPM_RC_SUCCESS) return result;
101 
102 // Command output
103        // Copy temporary variable to output, reserve the space for integrity
104        hashSize = sizeof(UINT16) +
105                   CryptGetHashDigestSize(newParent->publicArea.nameAlg);
106        out->outDuplicate.t.size = privateBlob.t.size;
107        MemoryCopy(out->outDuplicate.t.buffer + hashSize, privateBlob.t.buffer,
108                   privateBlob.t.size, sizeof(out->outDuplicate.t.buffer));
109 
110        // Produce outer wrapper for output
111        out->outDuplicate.t.size = ProduceOuterWrap(in->newParent, &in->name,
112                                   newParent->publicArea.nameAlg,
113                                   (TPM2B_SEED *) &data,
114                                   FALSE,
115                                   out->outDuplicate.t.size,
116                                   out->outDuplicate.t.buffer);
117 
118    }
119    else // New parent is a null key so there is no seed
120    {
121        out->outSymSeed.t.size = 0;
122 
123        // Copy privateBlob directly
124        out->outDuplicate = privateBlob;
125    }
126 
127    return TPM_RC_SUCCESS;
128 }
129