aboutsummaryrefslogtreecommitdiff
path: root/Import.c
blob: fef4b664759e2381d6c5ac6f0d0816be6017d463 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 3: Commands
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014

#include "InternalRoutines.h"
#include "Import_fp.h"
#include "Object_spt_fp.h"
//
//
//    Error Returns                     Meaning
//
//    TPM_RC_ASYMMETRIC                 non-duplicable storage key represented by objectPublic and its
//                                      parent referenced by parentHandle have different public parameters
//    TPM_RC_ATTRIBUTES                 attributes FixedTPM and fixedParent of objectPublic are not both
//                                      CLEAR; or inSymSeed is nonempty and parentHandle does not
//                                      reference a decryption key; or objectPublic and parentHandle have
//                                      incompatible or inconsistent attributes; or encrytpedDuplication is
//                                      SET in objectPublic but the inner or outer wrapper is missing.
//
//    NOTE:           if the TPM provides parameter values, the parameter number will indicate symmetricKey (missing
//                    inner wrapper) or inSymSeed (missing outer wrapper).
//
//
//    TPM_RC_BINDING                    duplicate and objectPublic are not cryptographically
//                                      bound
//
//    TPM_RC_ECC_POINT                  inSymSeed is nonempty and ECC point in inSymSeed is not on the
//                                      curve
//    TPM_RC_HASH                       non-duplicable storage key represented by objectPublic and its
//                                      parent referenced by parentHandle have different name algorithm
//    TPM_RC_INSUFFICIENT               inSymSeed is nonempty and failed to retrieve ECC point from the
//                                      secret; or unmarshaling sensitive value from duplicate failed the
//                                      result of inSymSeed decryption
//    TPM_RC_INTEGRITY                  duplicate integrity is broken
//    TPM_RC_KDF                        objectPublic representing decrypting keyed hash object specifies
//                                      invalid KDF
//    TPM_RC_KEY                        inconsistent parameters of objectPublic; or inSymSeed is nonempty
//                                      and parentHandle does not reference a key of supported type; or
//                                      invalid key size in objectPublic representing an asymmetric key
//    TPM_RC_NO_RESULT                  inSymSeed is nonempty and multiplication resulted in ECC point at
//                                      infinity
//    TPM_RC_OBJECT_MEMORY              no available object slot
//    TPM_RC_SCHEME                     inconsistent attributes decrypt, sign, restricted and key's scheme ID
//                                      in objectPublic; or hash algorithm is inconsistent with the scheme ID
//                                      for keyed hash object
//    TPM_RC_SIZE                       authPolicy size does not match digest size of the name algorithm in
//                                      objectPublic; or symmetricAlg and encryptionKey have different
//                                      sizes; or inSymSeed is nonempty and it size is not consistent with the
//                                      type of parentHandle; or unmarshaling sensitive value from duplicate
//                                      failed
//    TPM_RC_SYMMETRIC                  objectPublic is either a storage key with no symmetric algorithm or a
//                                      non-storage key with symmetric algorithm different from
//                                      TPM_ALG_NULL
//    TPM_RC_TYPE                       unsupported type of objectPublic; or non-duplicable storage key
//                                      represented by objectPublic and its parent referenced by
//                                      parentHandle are of different types; or parentHandle is not a storage
//                                      key; or only the public portion of parentHandle is loaded; or
//                                  objectPublic and duplicate are of different types
//     TPM_RC_VALUE                 nonempty inSymSeed and its numeric value is greater than the
//                                  modulus of the key referenced by parentHandle or inSymSeed is
//                                  larger than the size of the digest produced by the name algorithm of
//                                  the symmetric key referenced by parentHandle
//
TPM_RC
TPM2_Import(
   Import_In         *in,            // IN: input parameter list
   Import_Out        *out            // OUT: output parameter list
   )
{

   TPM_RC                   result = TPM_RC_SUCCESS;
   OBJECT                   *parentObject;
   TPM2B_DATA               data;                   // symmetric key
   TPMT_SENSITIVE           sensitive;
   TPM2B_NAME               name;

   UINT16                   innerKeySize = 0;             // encrypt key size for inner
                                                          // wrapper

// Input Validation

   // FixedTPM and fixedParent must be CLEAR
   if(   in->objectPublic.t.publicArea.objectAttributes.fixedTPM == SET
      || in->objectPublic.t.publicArea.objectAttributes.fixedParent == SET)
       return TPM_RC_ATTRIBUTES + RC_Import_objectPublic;

   // Get parent pointer
   parentObject = ObjectGet(in->parentHandle);

   if(!AreAttributesForParent(parentObject))
       return TPM_RC_TYPE + RC_Import_parentHandle;

   if(in->symmetricAlg.algorithm != TPM_ALG_NULL)
   {
       // Get inner wrap key size
       innerKeySize = in->symmetricAlg.keyBits.sym;
       // Input symmetric key must match the size of algorithm.
       if(in->encryptionKey.t.size != (innerKeySize + 7) / 8)
           return TPM_RC_SIZE + RC_Import_encryptionKey;
   }
   else
   {
       // If input symmetric algorithm is NULL, input symmetric key size must
       // be 0 as well
       if(in->encryptionKey.t.size != 0)
           return TPM_RC_SIZE + RC_Import_encryptionKey;
       // If encryptedDuplication is SET, then the object must have an inner
       // wrapper
       if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication)
           return TPM_RC_ATTRIBUTES + RC_Import_encryptionKey;
   }

   // See if there is an outer wrapper
   if(in->inSymSeed.t.size != 0)
   {
       // Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES,
       // TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT,
       // TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point
       result = CryptSecretDecrypt(in->parentHandle, NULL, "DUPLICATE",
                                   &in->inSymSeed, &data);
       pAssert(result != TPM_RC_BINDING);
//
       if(result != TPM_RC_SUCCESS)
           return RcSafeAddToResult(result, RC_Import_inSymSeed);
   }
   else
   {
       // If encrytpedDuplication is set, then the object must have an outer
       // wrapper
       if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication)
           return TPM_RC_ATTRIBUTES + RC_Import_inSymSeed;
       data.t.size = 0;
   }

   // Compute name of object
   ObjectComputeName(&(in->objectPublic.t.publicArea), &name);

   // Retrieve sensitive from private.
   // TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here.
   result = DuplicateToSensitive(&in->duplicate, &name, in->parentHandle,
                                 in->objectPublic.t.publicArea.nameAlg,
                                 (TPM2B_SEED *) &data, &in->symmetricAlg,
                                 &in->encryptionKey, &sensitive);
   if(result != TPM_RC_SUCCESS)
       return RcSafeAddToResult(result, RC_Import_duplicate);

   // If the parent of this object has fixedTPM SET, then fully validate this
   // object so that validation can be skipped when it is loaded
   if(parentObject->publicArea.objectAttributes.fixedTPM == SET)
   {
       TPM_HANDLE       objectHandle;

       // Perform self check on input public area. A TPM_RC_SIZE, TPM_RC_SCHEME,
       // TPM_RC_VALUE, TPM_RC_SYMMETRIC, TPM_RC_TYPE, TPM_RC_HASH,
       // TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES or TPM_RC_KDF error may be returned
       // at this point
       result = PublicAttributesValidation(TRUE, in->parentHandle,
                                           &in->objectPublic.t.publicArea);
       if(result != TPM_RC_SUCCESS)
           return RcSafeAddToResult(result, RC_Import_objectPublic);

       // Create internal object. A TPM_RC_KEY_SIZE, TPM_RC_KEY or
       // TPM_RC_OBJECT_MEMORY error may be returned at this point
       result = ObjectLoad(TPM_RH_NULL, &in->objectPublic.t.publicArea,
                           &sensitive, NULL, in->parentHandle, FALSE,
                           &objectHandle);
       if(result != TPM_RC_SUCCESS)
           return result;

       // Don't need the object, just needed the checks to be performed so
       // flush the object
       ObjectFlush(objectHandle);
   }

// Command output

   // Prepare output private data from sensitive
   SensitiveToPrivate(&sensitive, &name, in->parentHandle,
                      in->objectPublic.t.publicArea.nameAlg,
                      &out->outPrivate);

   return TPM_RC_SUCCESS;
}