1 | // =================================================================== |
---|
2 | // |
---|
3 | // Copyright (c) 2005, Intel Corp. |
---|
4 | // All rights reserved. |
---|
5 | // |
---|
6 | // Redistribution and use in source and binary forms, with or without |
---|
7 | // modification, are permitted provided that the following conditions |
---|
8 | // are met: |
---|
9 | // |
---|
10 | // * Redistributions of source code must retain the above copyright |
---|
11 | // notice, this list of conditions and the following disclaimer. |
---|
12 | // * Redistributions in binary form must reproduce the above |
---|
13 | // copyright notice, this list of conditions and the following |
---|
14 | // disclaimer in the documentation and/or other materials provided |
---|
15 | // with the distribution. |
---|
16 | // * Neither the name of Intel Corporation nor the names of its |
---|
17 | // contributors may be used to endorse or promote products derived |
---|
18 | // from this software without specific prior written permission. |
---|
19 | // |
---|
20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
---|
21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
---|
22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
---|
23 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
---|
24 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
---|
25 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
---|
26 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
---|
27 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
---|
28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
---|
29 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
---|
30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
---|
31 | // OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
32 | // =================================================================== |
---|
33 | // |
---|
34 | // dmictl.c |
---|
35 | // |
---|
36 | // Functions for creating and destroying DMIs |
---|
37 | // |
---|
38 | // ================================================================== |
---|
39 | |
---|
40 | #include <stdio.h> |
---|
41 | #include <unistd.h> |
---|
42 | #include <string.h> |
---|
43 | |
---|
44 | #include "vtpmpriv.h" |
---|
45 | #include "bsg.h" |
---|
46 | #include "buffer.h" |
---|
47 | #include "log.h" |
---|
48 | #include "hashtable.h" |
---|
49 | |
---|
50 | TPM_RESULT VTPM_Handle_Migrate_In( const buffer_t *param_buf, |
---|
51 | buffer_t *result_buf) { |
---|
52 | |
---|
53 | TPM_RESULT status=TPM_FAIL; |
---|
54 | VTPM_DMI_RESOURCE *mig_dmi=NULL; |
---|
55 | UINT32 dmi_id; |
---|
56 | buffer_t dmi_state_abuf = NULL_BUF, enc_dmi_abuf = NULL_BUF, clear_dmi_blob = NULL_BUF; |
---|
57 | |
---|
58 | if (param_buf == NULL) { |
---|
59 | vtpmlogerror(VTPM_LOG_VTPM, "Migration Out Failed due to bad parameter.\n"); |
---|
60 | status = TPM_BAD_PARAMETER; |
---|
61 | goto abort_egress; |
---|
62 | } |
---|
63 | |
---|
64 | struct pack_buf_t enc_dmi_state_pack; |
---|
65 | |
---|
66 | BSG_UnpackList(param_buf->bytes, 2, |
---|
67 | BSG_TYPE_UINT32, &dmi_id, |
---|
68 | BSG_TPM_SIZE32_DATA, &enc_dmi_state_pack) ; |
---|
69 | |
---|
70 | vtpmloginfo(VTPM_LOG_VTPM, "Migrating VTPM in dmi %d.\n", dmi_id); |
---|
71 | |
---|
72 | mig_dmi = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi_id); |
---|
73 | if (mig_dmi) { |
---|
74 | vtpmlogerror(VTPM_LOG_VTPM, "Incoming VTPM claims unavailable id: %d.\n", dmi_id); |
---|
75 | status = TPM_BAD_PARAMETER; |
---|
76 | goto abort_egress; |
---|
77 | } |
---|
78 | |
---|
79 | /** UnBind Blob **/ |
---|
80 | TPMTRYRETURN( buffer_init_alias_convert( &enc_dmi_abuf, |
---|
81 | enc_dmi_state_pack.size, |
---|
82 | enc_dmi_state_pack.data) ); |
---|
83 | |
---|
84 | TPMTRYRETURN( envelope_decrypt( &enc_dmi_abuf, |
---|
85 | vtpm_globals->manager_tcs_handle, |
---|
86 | vtpm_globals->storageKeyHandle, |
---|
87 | (const TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth, |
---|
88 | &clear_dmi_blob) ); |
---|
89 | |
---|
90 | // Create new dmi |
---|
91 | TPMTRYRETURN( init_dmi(dmi_id, VTPM_TYPE_MIGRATABLE, &mig_dmi ) ); |
---|
92 | |
---|
93 | /** Open Blob **/ |
---|
94 | struct pack_buf_t dmi_state_pack; |
---|
95 | |
---|
96 | BSG_UnpackList(clear_dmi_blob.bytes, 2, |
---|
97 | BSG_TPM_DIGEST, &mig_dmi->DMI_measurement, |
---|
98 | BSG_TPM_SIZE32_DATA, &dmi_state_pack); |
---|
99 | |
---|
100 | TPMTRYRETURN( buffer_init_alias_convert(&dmi_state_abuf, |
---|
101 | dmi_state_pack.size, |
---|
102 | dmi_state_pack.data) ); |
---|
103 | |
---|
104 | TPMTRYRETURN( VTPM_Handle_Save_NVM(mig_dmi, &dmi_state_abuf, NULL ) ); |
---|
105 | |
---|
106 | status=TPM_SUCCESS; |
---|
107 | goto egress; |
---|
108 | |
---|
109 | abort_egress: |
---|
110 | vtpmlogerror(VTPM_LOG_VTPM, "VTPM Migration IN of instance %d failed because of %s.\n", dmi_id, tpm_get_error_name(status) ); |
---|
111 | |
---|
112 | egress: |
---|
113 | buffer_free(&clear_dmi_blob); |
---|
114 | buffer_free(&dmi_state_abuf); |
---|
115 | |
---|
116 | return status; |
---|
117 | } |
---|
118 | |
---|
119 | TPM_RESULT VTPM_Handle_Migrate_Out( const buffer_t *param_buf, |
---|
120 | buffer_t *result_buf) { |
---|
121 | |
---|
122 | TPM_RESULT status=TPM_FAIL; |
---|
123 | VTPM_DMI_RESOURCE *mig_dmi; |
---|
124 | UINT32 dmi_id; |
---|
125 | VTPM_MIGKEY_LIST *last_mig, *mig_key; |
---|
126 | buffer_t dmi_state=NULL_BUF, clear_dmi_blob=NULL_BUF; |
---|
127 | |
---|
128 | if (param_buf == NULL) { |
---|
129 | vtpmlogerror(VTPM_LOG_VTPM, "Migration Out Failed due to bad parameter.\n"); |
---|
130 | status = TPM_BAD_PARAMETER; |
---|
131 | goto abort_egress; |
---|
132 | } |
---|
133 | |
---|
134 | struct pack_buf_t name_pack; |
---|
135 | |
---|
136 | BSG_UnpackList( param_buf->bytes, 2, |
---|
137 | BSG_TYPE_UINT32, &dmi_id, |
---|
138 | BSG_TPM_SIZE32_DATA, &name_pack); |
---|
139 | |
---|
140 | vtpmloginfo(VTPM_LOG_VTPM, "Migrating out dmi %d.\n", dmi_id); |
---|
141 | |
---|
142 | mig_dmi = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi_id); |
---|
143 | if (mig_dmi == NULL) { |
---|
144 | vtpmlogerror(VTPM_LOG_VTPM, "Non-existent VTPM instance (%d) in migration.\n", dmi_id ); |
---|
145 | status = TPM_BAD_PARAMETER; |
---|
146 | goto abort_egress; |
---|
147 | } |
---|
148 | |
---|
149 | if (mig_dmi->dmi_type != VTPM_TYPE_MIGRATABLE) { |
---|
150 | vtpmlogerror(VTPM_LOG_VTPM, "Bad VTPM type (%d) in migration of instance (%d).\n", mig_dmi->dmi_type, dmi_id ); |
---|
151 | status = TPM_BAD_PARAMETER; |
---|
152 | goto abort_egress; |
---|
153 | } |
---|
154 | |
---|
155 | /** Find migration key for dest **/ |
---|
156 | last_mig = NULL; |
---|
157 | mig_key = vtpm_globals->mig_keys; |
---|
158 | while (mig_key != NULL) { |
---|
159 | if (mig_key->name_size == name_pack.size) |
---|
160 | if (memcmp(mig_key->name, name_pack.data, name_pack.size) == 0) { |
---|
161 | break; |
---|
162 | } |
---|
163 | |
---|
164 | last_mig = mig_key; |
---|
165 | mig_key = mig_key->next; |
---|
166 | } |
---|
167 | |
---|
168 | if (!mig_key) { |
---|
169 | vtpmlogerror(VTPM_LOG_VTPM, "Unknown Migration target host.\n"); |
---|
170 | status = TPM_BAD_PARAMETER; |
---|
171 | goto abort_egress; |
---|
172 | } |
---|
173 | |
---|
174 | /** Mark vtpm as migrated **/ |
---|
175 | mig_dmi->dmi_type = VTPM_TYPE_MIGRATED; |
---|
176 | |
---|
177 | /** Build Blob **/ |
---|
178 | TPMTRYRETURN( VTPM_Handle_Load_NVM(mig_dmi, NULL, &dmi_state) ); |
---|
179 | |
---|
180 | TPMTRYRETURN( buffer_init(&clear_dmi_blob, sizeof(TPM_DIGEST) + sizeof(UINT32) + buffer_len(&dmi_state), NULL ) ); |
---|
181 | |
---|
182 | struct pack_constbuf_t dmi_state_pack; |
---|
183 | |
---|
184 | dmi_state_pack.size = buffer_len(&dmi_state); |
---|
185 | dmi_state_pack.data = dmi_state.bytes; |
---|
186 | |
---|
187 | BSG_PackList(clear_dmi_blob.bytes, 2, |
---|
188 | BSG_TPM_DIGEST, &mig_dmi->DMI_measurement, |
---|
189 | BSG_TPM_SIZE32_DATA, &dmi_state_pack); |
---|
190 | |
---|
191 | /** Bind Blob **/ |
---|
192 | TPMTRYRETURN( envelope_encrypt( &clear_dmi_blob, |
---|
193 | &mig_key->key, |
---|
194 | result_buf) ); |
---|
195 | |
---|
196 | if (last_mig) |
---|
197 | last_mig->next = mig_key->next; |
---|
198 | else |
---|
199 | vtpm_globals->mig_keys = mig_key->next; |
---|
200 | |
---|
201 | free(mig_key->name); |
---|
202 | free(mig_key); |
---|
203 | |
---|
204 | status=TPM_SUCCESS; |
---|
205 | goto egress; |
---|
206 | |
---|
207 | abort_egress: |
---|
208 | vtpmlogerror(VTPM_LOG_VTPM, "VTPM Migration OUT of instance %d failed because of %s. Migratoin recovery may be needed.\n", dmi_id, tpm_get_error_name(status) ); |
---|
209 | |
---|
210 | //TODO: Create and implement a policy for what happens to mig_key on failed migrations. |
---|
211 | |
---|
212 | egress: |
---|
213 | |
---|
214 | buffer_free(&clear_dmi_blob); |
---|
215 | buffer_free(&dmi_state); |
---|
216 | |
---|
217 | return status; |
---|
218 | } |
---|
219 | |
---|
220 | |
---|
221 | TPM_RESULT VTPM_Handle_Get_Migration_key( const buffer_t *param_buf, |
---|
222 | buffer_t *result_buf) { |
---|
223 | |
---|
224 | TPM_RESULT status=TPM_FAIL; |
---|
225 | |
---|
226 | vtpmloginfo(VTPM_LOG_VTPM, "Getting Migration Public Key.\n"); |
---|
227 | |
---|
228 | struct pack_buf_t pubkey_exp_pack, pubkey_mod_pack; |
---|
229 | TPM_KEY mig_key; |
---|
230 | |
---|
231 | // Unpack/return key structure |
---|
232 | BSG_Unpack(BSG_TPM_KEY, vtpm_globals->storageKeyWrap.bytes , &mig_key); |
---|
233 | TPM_RSA_KEY_PARMS rsaKeyParms; |
---|
234 | |
---|
235 | BSG_Unpack(BSG_TPM_RSA_KEY_PARMS, |
---|
236 | mig_key.algorithmParms.parms, |
---|
237 | &rsaKeyParms); |
---|
238 | |
---|
239 | pubkey_exp_pack.size = rsaKeyParms.exponentSize; |
---|
240 | pubkey_exp_pack.data = rsaKeyParms.exponent; |
---|
241 | pubkey_mod_pack.size = mig_key.pubKey.keyLength; |
---|
242 | pubkey_mod_pack.data = mig_key.pubKey.key; |
---|
243 | |
---|
244 | TPMTRYRETURN( buffer_init( result_buf, 2*sizeof(UINT32) + |
---|
245 | pubkey_exp_pack.size + |
---|
246 | pubkey_mod_pack.size, NULL ) ); |
---|
247 | |
---|
248 | BSG_PackList( result_buf->bytes, 2, |
---|
249 | BSG_TPM_SIZE32_DATA, &pubkey_exp_pack, |
---|
250 | BSG_TPM_SIZE32_DATA, &pubkey_mod_pack); |
---|
251 | |
---|
252 | |
---|
253 | status=TPM_SUCCESS; |
---|
254 | goto egress; |
---|
255 | |
---|
256 | abort_egress: |
---|
257 | vtpmlogerror(VTPM_LOG_VTPM, "VTPM Get Migration Key failed because of %s.\n", tpm_get_error_name(status) ); |
---|
258 | egress: |
---|
259 | |
---|
260 | return status; |
---|
261 | } |
---|
262 | |
---|
263 | TPM_RESULT VTPM_Handle_Load_Migration_key( const buffer_t *param_buf, |
---|
264 | buffer_t *result_buf) { |
---|
265 | |
---|
266 | TPM_RESULT status=TPM_FAIL; |
---|
267 | VTPM_MIGKEY_LIST *mig_key; |
---|
268 | |
---|
269 | vtpmloginfo(VTPM_LOG_VTPM, "Loading Migration Public Key.\n"); |
---|
270 | |
---|
271 | //FIXME: Review all uses of unpacking pack_buf_t and ensure free. |
---|
272 | //FIXME: Review all declarations/initializations of buffer_t that could have a goto that skips them and then tries to free them |
---|
273 | |
---|
274 | struct pack_buf_t name_pack, pubkey_exp_pack, pubkey_mod_pack; |
---|
275 | |
---|
276 | //FIXME: scan list and verify name is not already in the list |
---|
277 | |
---|
278 | BSG_UnpackList( param_buf->bytes, 3, |
---|
279 | BSG_TPM_SIZE32_DATA, &name_pack, |
---|
280 | BSG_TPM_SIZE32_DATA, &pubkey_exp_pack, |
---|
281 | BSG_TPM_SIZE32_DATA, &pubkey_mod_pack); |
---|
282 | |
---|
283 | //TODO: Maintain a persistent list for pub_keys. |
---|
284 | //TODO: Verify pub_key is trusted |
---|
285 | |
---|
286 | mig_key = (VTPM_MIGKEY_LIST *) malloc(sizeof(VTPM_MIGKEY_LIST)); |
---|
287 | memset(mig_key, 0, sizeof(VTPM_MIGKEY_LIST) ); |
---|
288 | mig_key->name_size = name_pack.size; |
---|
289 | mig_key->name = name_pack.data; |
---|
290 | |
---|
291 | mig_key->key.encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1; |
---|
292 | Crypto_RSABuildCryptoInfoPublic( pubkey_exp_pack.size, |
---|
293 | pubkey_exp_pack.data, |
---|
294 | pubkey_mod_pack.size, |
---|
295 | pubkey_mod_pack.data, |
---|
296 | &mig_key->key); |
---|
297 | |
---|
298 | |
---|
299 | mig_key->next = vtpm_globals->mig_keys; |
---|
300 | vtpm_globals->mig_keys = mig_key; |
---|
301 | |
---|
302 | // free(name_pack.data); Do not free. data is now part of mig_key. |
---|
303 | free(pubkey_exp_pack.data); |
---|
304 | free(pubkey_mod_pack.data); |
---|
305 | |
---|
306 | return TPM_SUCCESS; |
---|
307 | } |
---|