1 2/* 3 * Licensed Materials - Property of IBM 4 * 5 * trousers - An open source TCG Software Stack 6 * 7 * (C) Copyright International Business Machines Corp. 2004-2006 8 * 9 */ 10 11#include <stdlib.h> 12#include <stdio.h> 13#include <string.h> 14#include <inttypes.h> 15 16#include "trousers/tss.h" 17#include "trousers/trousers.h" 18#include "trousers_types.h" 19#include "spi_utils.h" 20#include "capabilities.h" 21#include "tsplog.h" 22#include "obj.h" 23 24 25TSS_RESULT 26Tspi_TPM_AuthorizeMigrationTicket(TSS_HTPM hTPM, /* in */ 27 TSS_HKEY hMigrationKey, /* in */ 28 TSS_MIGRATION_SCHEME migrationScheme, /* in */ 29 UINT32 * pulMigTicketLength, /* out */ 30 BYTE ** prgbMigTicket) /* out */ 31{ 32 UINT64 offset; 33 TCPA_DIGEST digest; 34 TCPA_RESULT result; 35 TSS_HPOLICY hOwnerPolicy; 36 UINT32 migrationKeySize; 37 BYTE *migrationKeyBlob; 38 TSS_KEY tssKey; 39 BYTE pubKeyBlob[0x1000]; 40 TPM_AUTH ownerAuth; 41 UINT32 pubKeySize; 42 TSS_HCONTEXT tspContext; 43 UINT32 tpmMigrationScheme; 44 Trspi_HashCtx hashCtx; 45 46 if (pulMigTicketLength == NULL || prgbMigTicket == NULL) 47 return TSPERR(TSS_E_BAD_PARAMETER); 48 49 if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext))) 50 return result; 51 52 /* get the tpm Policy */ 53 if ((result = obj_tpm_get_policy(hTPM, TSS_POLICY_USAGE, &hOwnerPolicy))) 54 return result; 55 56 switch (migrationScheme) { 57 case TSS_MS_MIGRATE: 58 tpmMigrationScheme = TCPA_MS_MIGRATE; 59 break; 60 case TSS_MS_REWRAP: 61 tpmMigrationScheme = TCPA_MS_REWRAP; 62 break; 63 case TSS_MS_MAINT: 64 tpmMigrationScheme = TCPA_MS_MAINT; 65 break; 66#ifdef TSS_BUILD_CMK 67 case TSS_MS_RESTRICT_MIGRATE: 68 tpmMigrationScheme = TPM_MS_RESTRICT_MIGRATE; 69 break; 70 71 case TSS_MS_RESTRICT_APPROVE_DOUBLE: 72 tpmMigrationScheme = TPM_MS_RESTRICT_APPROVE_DOUBLE; 73 break; 74#endif 75 default: 76 return TSPERR(TSS_E_BAD_PARAMETER); 77 break; 78 } 79 80 /* Get the migration key blob */ 81 if ((result = obj_rsakey_get_blob(hMigrationKey, &migrationKeySize, &migrationKeyBlob))) 82 return result; 83 84 /* First, turn the keyBlob into a TSS_KEY structure */ 85 offset = 0; 86 memset(&tssKey, 0, sizeof(TSS_KEY)); 87 if ((result = UnloadBlob_TSS_KEY(&offset, migrationKeyBlob, &tssKey))) { 88 free_tspi(tspContext, migrationKeyBlob); 89 return result; 90 } 91 free_tspi(tspContext, migrationKeyBlob); 92 93 /* Then pull the _PUBKEY portion out of that struct into a blob */ 94 offset = 0; 95 Trspi_LoadBlob_KEY_PARMS(&offset, pubKeyBlob, &tssKey.algorithmParms); 96 Trspi_LoadBlob_STORE_PUBKEY(&offset, pubKeyBlob, &tssKey.pubKey); 97 pubKeySize = offset; 98 free_key_refs(&tssKey); 99 100 /* Auth */ 101 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 102 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_AuthorizeMigrationKey); 103 result |= Trspi_Hash_UINT16(&hashCtx, tpmMigrationScheme); 104 result |= Trspi_HashUpdate(&hashCtx, pubKeySize, pubKeyBlob); 105 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 106 return result; 107 108 if ((result = secret_PerformAuth_OIAP(hTPM, TPM_ORD_AuthorizeMigrationKey, hOwnerPolicy, 109 FALSE, &digest, &ownerAuth))) 110 return result; 111 112 /* Send command */ 113 if ((result = TCS_API(tspContext)->AuthorizeMigrationKey(tspContext, migrationScheme, 114 pubKeySize, pubKeyBlob, &ownerAuth, 115 pulMigTicketLength, 116 prgbMigTicket))) 117 return result; 118 119 /* Validate Auth */ 120 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 121 result |= Trspi_Hash_UINT32(&hashCtx, result); 122 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_AuthorizeMigrationKey); 123 result |= Trspi_HashUpdate(&hashCtx, *pulMigTicketLength, *prgbMigTicket); 124 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) { 125 *pulMigTicketLength = 0; 126 free(*prgbMigTicket); 127 return result; 128 } 129 130 if ((result = obj_policy_validate_auth_oiap(hOwnerPolicy, &digest, &ownerAuth))) { 131 *pulMigTicketLength = 0; 132 free(*prgbMigTicket); 133 return result; 134 } 135 136 if ((result = __tspi_add_mem_entry(tspContext, *prgbMigTicket))) { 137 *pulMigTicketLength = 0; 138 free(*prgbMigTicket); 139 return result; 140 } 141 142 return TSS_SUCCESS; 143} 144 145TSS_RESULT 146Tspi_Key_CreateMigrationBlob(TSS_HKEY hKeyToMigrate, /* in */ 147 TSS_HKEY hParentKey, /* in */ 148 UINT32 ulMigTicketLength, /* in */ 149 BYTE * rgbMigTicket, /* in */ 150 UINT32 * pulRandomLength, /* out */ 151 BYTE ** prgbRandom, /* out */ 152 UINT32 * pulMigrationBlobLength, /* out */ 153 BYTE ** prgbMigrationBlob) /* out */ 154{ 155 TPM_AUTH parentAuth, entityAuth; 156 TPM_AUTH *pParentAuth; 157 TCPA_RESULT result; 158 UINT64 offset; 159 TCPA_DIGEST digest; 160 UINT32 keyToMigrateSize; 161 BYTE *keyToMigrateBlob = NULL; 162 TSS_HPOLICY hParentPolicy; 163 TSS_HPOLICY hMigratePolicy; 164 TCPA_MIGRATIONKEYAUTH migAuth; 165 TSS_KEY tssKey; 166 TCS_KEY_HANDLE parentHandle; 167 TSS_BOOL parentUsesAuth; 168 UINT32 randomSize; 169 BYTE *random = NULL; 170 UINT32 blobSize; 171 BYTE *blob = NULL; 172 TSS_HCONTEXT tspContext; 173 Trspi_HashCtx hashCtx; 174 175 memset(&tssKey, 0, sizeof(TSS_KEY)); 176 177 if (pulRandomLength == NULL || prgbRandom == NULL || rgbMigTicket == NULL || 178 pulMigrationBlobLength == NULL || prgbMigrationBlob == NULL) 179 return TSPERR(TSS_E_BAD_PARAMETER); 180 181 if (!obj_is_rsakey(hKeyToMigrate)) 182 return TSPERR(TSS_E_INVALID_HANDLE); 183 184 if ((result = obj_rsakey_get_tsp_context(hKeyToMigrate, &tspContext))) 185 return result; 186 187 if ((result = obj_rsakey_get_blob(hKeyToMigrate, &keyToMigrateSize, &keyToMigrateBlob))) 188 goto done; 189 190 if ((result = obj_rsakey_get_policy(hParentKey, TSS_POLICY_USAGE, &hParentPolicy, 191 &parentUsesAuth))) 192 goto done; 193 194 if ((result = obj_rsakey_get_policy(hKeyToMigrate, TSS_POLICY_MIGRATION, &hMigratePolicy, 195 NULL))) 196 goto done; 197 198 /* Parsing the migration scheme from the blob and key object */ 199 memset(&migAuth, 0, sizeof(TCPA_MIGRATIONKEYAUTH)); 200 201 offset = 0; 202 if ((result = Trspi_UnloadBlob_MIGRATIONKEYAUTH(&offset, rgbMigTicket, &migAuth))) 203 goto done; 204 205 /* free these now, since none are used below */ 206 free(migAuth.migrationKey.algorithmParms.parms); 207 migAuth.migrationKey.algorithmParms.parmSize = 0; 208 free(migAuth.migrationKey.pubKey.key); 209 migAuth.migrationKey.pubKey.keyLength = 0; 210 211 offset = 0; 212 if ((result = UnloadBlob_TSS_KEY(&offset, keyToMigrateBlob, &tssKey))) 213 goto done; 214 215 /* Generate the Authorization data */ 216 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 217 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CreateMigrationBlob); 218 result |= Trspi_Hash_UINT16(&hashCtx, migAuth.migrationScheme); 219 result |= Trspi_HashUpdate(&hashCtx, ulMigTicketLength, rgbMigTicket); 220 result |= Trspi_Hash_UINT32(&hashCtx, tssKey.encSize); 221 result |= Trspi_HashUpdate(&hashCtx, tssKey.encSize, tssKey.encData); 222 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 223 goto done; 224 225 if (parentUsesAuth) { 226 if ((result = secret_PerformAuth_OIAP(hParentPolicy, TPM_ORD_CreateMigrationBlob, 227 hParentPolicy, FALSE, &digest, 228 &parentAuth))) 229 goto done; 230 pParentAuth = &parentAuth; 231 } else { 232 pParentAuth = NULL; 233 } 234 235 if ((result = secret_PerformAuth_OIAP(hKeyToMigrate, TPM_ORD_CreateMigrationBlob, 236 hMigratePolicy, FALSE, &digest, &entityAuth))) 237 goto done; 238 239 if ((result = obj_rsakey_get_tcs_handle(hParentKey, &parentHandle))) 240 goto done; 241 242 if ((result = TCS_API(tspContext)->CreateMigrationBlob(tspContext, parentHandle, 243 migAuth.migrationScheme, 244 ulMigTicketLength, rgbMigTicket, 245 tssKey.encSize, tssKey.encData, 246 pParentAuth, &entityAuth, 247 &randomSize, &random, 248 &blobSize, &blob))) 249 goto done; 250 251 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 252 result |= Trspi_Hash_UINT32(&hashCtx, result); 253 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CreateMigrationBlob); 254 result |= Trspi_Hash_UINT32(&hashCtx, randomSize); 255 result |= Trspi_HashUpdate(&hashCtx, randomSize, random); 256 result |= Trspi_Hash_UINT32(&hashCtx, blobSize); 257 result |= Trspi_HashUpdate(&hashCtx, blobSize, blob); 258 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 259 goto done; 260 261 if (parentUsesAuth) { 262 if ((result = obj_policy_validate_auth_oiap(hParentPolicy, &digest, &parentAuth))) 263 goto done; 264 } 265 266 if ((result = obj_policy_validate_auth_oiap(hMigratePolicy, &digest, &entityAuth))) 267 goto done; 268 269 free(tssKey.encData); 270 tssKey.encSize = blobSize; 271 tssKey.encData = blob; 272 /* Set blob to null since it will now be freed during key ref freeing */ 273 blob = NULL; 274 275 offset = 0; 276 LoadBlob_TSS_KEY(&offset, NULL, &tssKey); 277 278 *pulMigrationBlobLength = offset; 279 *prgbMigrationBlob = calloc_tspi(tspContext, *pulMigrationBlobLength); 280 if (*prgbMigrationBlob == NULL) { 281 LogError("malloc of %u bytes failed.", *pulMigrationBlobLength); 282 result = TSPERR(TSS_E_OUTOFMEMORY); 283 goto done; 284 } 285 offset = 0; 286 LoadBlob_TSS_KEY(&offset, *prgbMigrationBlob, &tssKey); 287 288 if (randomSize) { 289 if ((result = __tspi_add_mem_entry(tspContext, random))) 290 goto done; 291 } 292 *pulRandomLength = randomSize; 293 *prgbRandom = random; 294 295done: 296 if (result) 297 free(random); 298 free_tspi(tspContext, keyToMigrateBlob); 299 free_key_refs(&tssKey); 300 free(blob); 301 302 return result; 303} 304 305TSS_RESULT 306Tspi_Key_ConvertMigrationBlob(TSS_HKEY hKeyToMigrate, /* in */ 307 TSS_HKEY hParentKey, /* in */ 308 UINT32 ulRandomLength, /* in */ 309 BYTE * rgbRandom, /* in */ 310 UINT32 ulMigrationBlobLength, /* in */ 311 BYTE * rgbMigrationBlob) /* in */ 312{ 313 TCPA_RESULT result; 314 TSS_KEY tssKey; 315 UINT32 outDataSize; 316 BYTE *outData = NULL; 317 TCS_KEY_HANDLE parentHandle; 318 TPM_AUTH parentAuth; 319 TSS_HPOLICY hParentPolicy; 320 TCPA_DIGEST digest; 321 TSS_BOOL useAuth; 322 TPM_AUTH *pParentAuth; 323 TSS_HCONTEXT tspContext; 324 Trspi_HashCtx hashCtx; 325 UINT64 offset; 326 327 memset(&tssKey, 0, sizeof(TSS_KEY)); 328 329 if ((result = obj_rsakey_get_tsp_context(hKeyToMigrate, &tspContext))) 330 return result; 331 332 if (!obj_is_rsakey(hParentKey)) 333 return TSPERR(TSS_E_INVALID_HANDLE); 334 335 /* Get the parent key handle */ 336 if ((result = obj_rsakey_get_tcs_handle(hParentKey, &parentHandle))) 337 return result; 338 339 /* Get the policy */ 340 if ((result = obj_rsakey_get_policy(hParentKey, TSS_POLICY_USAGE, 341 &hParentPolicy, &useAuth))) 342 return result; 343 344 offset = 0; 345 if ((result = UnloadBlob_TSS_KEY(&offset, rgbMigrationBlob, &tssKey))) 346 return result; 347 348 /* Generate the authorization */ 349 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 350 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ConvertMigrationBlob); 351 result |= Trspi_Hash_UINT32(&hashCtx, tssKey.encSize); 352 result |= Trspi_HashUpdate(&hashCtx, tssKey.encSize, tssKey.encData); 353 result |= Trspi_Hash_UINT32(&hashCtx, ulRandomLength); 354 result |= Trspi_HashUpdate(&hashCtx, ulRandomLength, rgbRandom); 355 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 356 goto done; 357 358 if (useAuth) { 359 if ((result = secret_PerformAuth_OIAP(hParentPolicy, TPM_ORD_ConvertMigrationBlob, 360 hParentPolicy, FALSE, &digest, &parentAuth))) 361 goto done; 362 pParentAuth = &parentAuth; 363 } else { 364 pParentAuth = NULL; 365 } 366 367 if ((result = TCS_API(tspContext)->ConvertMigrationBlob(tspContext, parentHandle, 368 tssKey.encSize, tssKey.encData, 369 ulRandomLength, rgbRandom, 370 pParentAuth, 371 &outDataSize, &outData))) 372 goto done; 373 374 /* add validation */ 375 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 376 result |= Trspi_Hash_UINT32(&hashCtx, result); 377 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ConvertMigrationBlob); 378 result |= Trspi_Hash_UINT32(&hashCtx, outDataSize); 379 result |= Trspi_HashUpdate(&hashCtx, outDataSize, outData); 380 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 381 goto done; 382 383 if (useAuth) { 384 if ((result = obj_policy_validate_auth_oiap(hParentPolicy, &digest, &parentAuth))) 385 goto done; 386 } 387 388 /* Set the key object to the now migrated key */ 389 if ((result = obj_rsakey_set_tcpakey(hKeyToMigrate, ulMigrationBlobLength, rgbMigrationBlob))) 390 goto done; 391 if ((result = obj_rsakey_set_privkey(hKeyToMigrate, TRUE, outDataSize, outData))) 392 goto done; 393 result = obj_rsakey_set_tcs_handle(hKeyToMigrate, 0); 394 395done: 396 free_key_refs(&tssKey); 397 free(outData); 398 399 return result; 400} 401