[34] | 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 | } |
---|