TSS_RESULT fill_key_info2(struct key_disk_cache *d, struct key_mem_cache *m, TSS_KM_KEYINFO2 *key_info) { BYTE tmp_blob[2048]; UINT16 tmp_blob_size = 2048; TSS_KEY tmp_key; UINT64 offset; TSS_RESULT result; if (m == NULL) { key_info->fIsLoaded = FALSE; /* read key from disk */ if ((result = ps_get_key_by_cache_entry(d, (BYTE *)&tmp_blob, &tmp_blob_size))) return result; offset = 0; /* XXX add a real context handle here */ if ((result = UnloadBlob_TSS_KEY(&offset, tmp_blob, &tmp_key))) return result; if (tmp_key.hdr.key12.tag == TPM_TAG_KEY12) { key_info->versionInfo.bMajor = TSS_SPEC_MAJOR; key_info->versionInfo.bMinor = TSS_SPEC_MINOR; key_info->versionInfo.bRevMajor = 0; key_info->versionInfo.bRevMajor = 0; } else memcpy(&key_info->versionInfo, &tmp_key.hdr.key11.ver, sizeof(TSS_VERSION)); memcpy(&key_info->bAuthDataUsage, &tmp_key.authDataUsage, sizeof(TCPA_AUTH_DATA_USAGE)); destroy_key_refs(&tmp_key); } else { if (m->tpm_handle == NULL_TPM_HANDLE) key_info->fIsLoaded = FALSE; else key_info->fIsLoaded = TRUE; if (m->blob->hdr.key12.tag == TPM_TAG_KEY12) { key_info->versionInfo.bMajor = TSS_SPEC_MAJOR; key_info->versionInfo.bMinor = TSS_SPEC_MINOR; key_info->versionInfo.bRevMajor = 0; key_info->versionInfo.bRevMajor = 0; } else memcpy(&key_info->versionInfo, &m->blob->hdr.key11.ver, sizeof(TSS_VERSION)); memcpy(&key_info->bAuthDataUsage, &m->blob->authDataUsage, sizeof(TCPA_AUTH_DATA_USAGE)); } memcpy(&key_info->keyUUID, &d->uuid, sizeof(TSS_UUID)); memcpy(&key_info->parentKeyUUID, &d->parent_uuid, sizeof(TSS_UUID)); /* Fill the two new TSS_KM_KEYINFO2 fields here */ key_info->persistentStorageTypeParent = d->flags & CACHE_FLAG_PARENT_PS_SYSTEM ? TSS_PS_TYPE_SYSTEM : TSS_PS_TYPE_USER; key_info->persistentStorageType = TSS_PS_TYPE_SYSTEM; return get_vendor_data(d, &key_info->ulVendorDataLength, &key_info->rgbVendorData); }
TSS_RESULT TCS_GetRegisteredKey_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ TSS_UUID *KeyUUID, /* in */ TSS_KM_KEYINFO ** ppKeyInfo) /* out */ { TSS_RESULT result; UINT64 offset; BYTE tcpaKeyBlob[1024]; TSS_KEY tcpaKey; UINT16 keySize = sizeof (tcpaKeyBlob); TSS_UUID parentUUID; /* This should be set in case we return before the malloc */ *ppKeyInfo = NULL; if ((result = ctx_verify_context(hContext))) return result; if ((result = ps_get_key_by_uuid(KeyUUID, tcpaKeyBlob, &keySize))) { return TCSERR(TSS_E_PS_KEY_NOTFOUND); } if ((result = getParentUUIDByUUID(KeyUUID, &parentUUID))) return TCSERR(TSS_E_FAIL); *ppKeyInfo = malloc(sizeof(TSS_KM_KEYINFO)); if (*ppKeyInfo == NULL) { LogError("malloc of %zd bytes failed.", sizeof(TSS_KM_KEYINFO)); return TCSERR(TSS_E_OUTOFMEMORY); } offset = 0; UnloadBlob_TSS_KEY(&offset, tcpaKeyBlob, &tcpaKey); (*ppKeyInfo)->bAuthDataUsage = tcpaKey.authDataUsage; (*ppKeyInfo)->fIsLoaded = FALSE; if (tcpaKey.hdr.key12.tag == TPM_TAG_KEY12) { (*ppKeyInfo)->versionInfo.bMajor = TSS_SPEC_MAJOR; (*ppKeyInfo)->versionInfo.bMinor = TSS_SPEC_MINOR; (*ppKeyInfo)->versionInfo.bRevMajor = 0; (*ppKeyInfo)->versionInfo.bRevMinor = 0; } else { (*ppKeyInfo)->versionInfo.bMajor = tcpaKey.hdr.key11.ver.major; (*ppKeyInfo)->versionInfo.bMinor = tcpaKey.hdr.key11.ver.minor; (*ppKeyInfo)->versionInfo.bRevMajor = tcpaKey.hdr.key11.ver.revMajor; (*ppKeyInfo)->versionInfo.bRevMinor = tcpaKey.hdr.key11.ver.revMinor; } memcpy(&((*ppKeyInfo)->keyUUID), KeyUUID, sizeof(TSS_UUID)); (*ppKeyInfo)->ulVendorDataLength = 0; (*ppKeyInfo)->rgbVendorData = 0; memcpy(&((*ppKeyInfo)->parentKeyUUID), &parentUUID, sizeof(TSS_UUID)); return TSS_SUCCESS; }
TSS_RESULT copy_key_info2(int fd, TSS_KM_KEYINFO2 *ki, struct key_disk_cache *c) { TSS_KEY key; BYTE blob[4096]; UINT64 offset; TSS_RESULT result; off_t off; /* Set the file pointer to the offset that the key blob is at */ off = lseek(fd, TSSPS_BLOB_DATA_OFFSET(c), SEEK_SET); if (off == ((off_t)-1)) { LogDebug("lseek: %s", strerror(errno)); return TSPERR(TSS_E_INTERNAL_ERROR); } /* Read in the key blob */ if ((result = read_data(fd, (void *)blob, c->blob_size))) { LogDebug("%s", __FUNCTION__); return result; } /* Expand the blob into a useable form */ offset = 0; if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key))) return result; if (key.hdr.key12.tag == TPM_TAG_KEY12) { ki->versionInfo.bMajor = TSS_SPEC_MAJOR; ki->versionInfo.bMinor = TSS_SPEC_MINOR; ki->versionInfo.bRevMajor = 0; ki->versionInfo.bRevMinor = 0; } else memcpy(&ki->versionInfo, &key.hdr.key11.ver, sizeof(TSS_VERSION)); memcpy(&ki->keyUUID, &c->uuid, sizeof(TSS_UUID)); memcpy(&ki->parentKeyUUID, &c->parent_uuid, sizeof(TSS_UUID)); /* CHECK: fill the two new fields of TSS_KM_KEYINFO2 */ ki->persistentStorageType = TSS_PS_TYPE_USER; ki->persistentStorageTypeParent = c->flags & CACHE_FLAG_PARENT_PS_SYSTEM ? TSS_PS_TYPE_SYSTEM : TSS_PS_TYPE_USER; ki->bAuthDataUsage = key.authDataUsage; free_key_refs(&key); return TSS_SUCCESS; }
/* * disk store format: * * TrouSerS 0.2.0 and before: * Version 0: cached? * [UINT32 num_keys_on_disk] * [TSS_UUID uuid0 ] yes * [TSS_UUID uuid_parent0 ] yes * [UINT16 pub_data_size0 ] yes * [UINT16 blob_size0 ] yes * [UINT16 cache_flags0 ] yes * [BYTE[] pub_data0 ] * [BYTE[] blob0 ] * [...] * * TrouSerS 0.2.1+ * Version 1: cached? * [BYTE PS version = '\1'] * [UINT32 num_keys_on_disk ] * [TSS_UUID uuid0 ] yes * [TSS_UUID uuid_parent0 ] yes * [UINT16 pub_data_size0 ] yes * [UINT16 blob_size0 ] yes * [UINT32 vendor_data_size0] yes * [UINT16 cache_flags0 ] yes * [BYTE[] pub_data0 ] * [BYTE[] blob0 ] * [BYTE[] vendor_data0 ] * [...] * */ TSS_RESULT psfile_write_key(int fd, TSS_UUID *uuid, TSS_UUID *parent_uuid, UINT32 *parent_ps, BYTE *vendor_data, UINT32 vendor_size, BYTE *key_blob, UINT16 key_blob_size) { TSS_KEY key; UINT16 pub_key_size, cache_flags = CACHE_FLAG_VALID; UINT64 offset; int rc = 0; /* leaving the cache flag for parent ps type as 0 implies TSS_PS_TYPE_USER */ if (*parent_ps == TSS_PS_TYPE_SYSTEM) cache_flags |= CACHE_FLAG_PARENT_PS_SYSTEM; /* Unload the blob to get the public key */ offset = 0; if ((rc = UnloadBlob_TSS_KEY(&offset, key_blob, &key))) return rc; pub_key_size = key.pubKey.keyLength; if ((rc = write_key_init(fd, pub_key_size, key_blob_size, vendor_size)) < 0) goto done; /* offset now holds the number of bytes from the beginning of the file * the key will be stored at */ offset = rc; #ifdef TSS_DEBUG if (offset == 0) LogDebug("ERROR: key being written with offset 0!!"); #endif /* [TSS_UUID uuid0 ] yes */ if ((rc = write_data(fd, (void *)uuid, sizeof(TSS_UUID)))) { LogError("%s", __FUNCTION__); goto done; } /* [TSS_UUID uuid_parent0 ] yes */ if ((rc = write_data(fd, (void *)parent_uuid, sizeof(TSS_UUID)))) { LogError("%s", __FUNCTION__); goto done; } /* [UINT16 pub_data_size0 ] yes */ if ((rc = write_data(fd, &pub_key_size, sizeof(UINT16)))) { LogError("%s", __FUNCTION__); goto done; } /* [UINT16 blob_size0 ] yes */ if ((rc = write_data(fd, &key_blob_size, sizeof(UINT16)))) { LogError("%s", __FUNCTION__); goto done; } /* [UINT32 vendor_data_size0 ] yes */ if ((rc = write_data(fd, &vendor_size, sizeof(UINT32)))) { LogError("%s", __FUNCTION__); goto done; } /* [UINT16 cache_flags0 ] yes */ if ((rc = write_data(fd, &cache_flags, sizeof(UINT16)))) { LogError("%s", __FUNCTION__); goto done; } /* [BYTE[] pub_data0 ] no */ if ((rc = write_data(fd, (void *)key.pubKey.key, pub_key_size))) { LogError("%s", __FUNCTION__); goto done; } /* [BYTE[] blob0 ] no */ if ((rc = write_data(fd, (void *)key_blob, key_blob_size))) { LogError("%s", __FUNCTION__); goto done; } /* [BYTE[] vendor_data0 ] no */ if (vendor_size > 0) { if ((rc = write_data(fd, (void *)vendor_data, vendor_size))) { LogError("%s", __FUNCTION__); goto done; } } if ((rc = cache_key((UINT32)offset, cache_flags, uuid, parent_uuid, pub_key_size, key_blob_size, vendor_size))) goto done; done: destroy_key_refs(&key); return rc; }
TSS_RESULT TCSP_TakeOwnership_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ UINT16 protocolID, /* in */ UINT32 encOwnerAuthSize, /* in */ BYTE * encOwnerAuth, /* in */ UINT32 encSrkAuthSize, /* in */ BYTE * encSrkAuth, /* in */ UINT32 srkInfoSize, /*in */ BYTE * srkInfo, /*in */ TPM_AUTH * ownerAuth, /* in, out */ UINT32 * srkKeySize, /*out */ BYTE ** srkKey) /*out */ { UINT64 offset; UINT32 paramSize; TSS_RESULT result; TSS_KEY srkKeyContainer; BYTE fake_pubkey[256] = { 0, }, fake_srk[2048] = { 0, }; BYTE oldAuthDataUsage; BYTE txBlob[TSS_TPM_TXBLOB_SIZE]; if ((result = ctx_verify_context(hContext))) goto done; if ((result = auth_mgr_check(hContext, &ownerAuth->AuthHandle))) goto done; /* Check on the Atmel Bug Patch */ offset = 0; UnloadBlob_TSS_KEY(&offset, srkInfo, &srkKeyContainer); oldAuthDataUsage = srkKeyContainer.authDataUsage; LogDebug("auth data usage is %.2X", oldAuthDataUsage); offset = 0; if ((result = tpm_rqu_build(TPM_ORD_TakeOwnership, &offset, txBlob, protocolID, encOwnerAuthSize, encOwnerAuth, encSrkAuthSize, encSrkAuth, srkInfoSize, srkInfo, ownerAuth))) return result; if ((result = req_mgr_submit_req(txBlob))) goto done; result = UnloadBlob_Header(txBlob, ¶mSize); if (!result) { if ((result = tpm_rsp_parse(TPM_ORD_TakeOwnership, txBlob, paramSize, srkKeySize, srkKey, ownerAuth))) goto done; offset = 0; if ((result = UnloadBlob_TSS_KEY(&offset, *srkKey, &srkKeyContainer))) { *srkKeySize = 0; free(*srkKey); goto done; } if (srkKeyContainer.authDataUsage != oldAuthDataUsage) { LogDebug("AuthDataUsage was changed by TPM. Atmel Bug. Fixing it in PS"); srkKeyContainer.authDataUsage = oldAuthDataUsage; } #ifdef TSS_BUILD_PS { BYTE *save; /* Once the key file is created, it stays forever. There could be * migratable keys in the hierarchy that are still useful to someone. */ result = ps_remove_key(&SRK_UUID); if (result != TSS_SUCCESS && result != TCSERR(TSS_E_PS_KEY_NOTFOUND)) { destroy_key_refs(&srkKeyContainer); LogError("Error removing SRK from key file."); *srkKeySize = 0; free(*srkKey); goto done; } /* Set the SRK pubkey to all 0's before writing the SRK to disk, this is for * privacy reasons as outlined in the TSS spec */ save = srkKeyContainer.pubKey.key; srkKeyContainer.pubKey.key = fake_pubkey; offset = 0; LoadBlob_TSS_KEY(&offset, fake_srk, &srkKeyContainer); if ((result = ps_write_key(&SRK_UUID, &NULL_UUID, NULL, 0, fake_srk, offset))) { destroy_key_refs(&srkKeyContainer); LogError("Error writing SRK to disk"); *srkKeySize = 0; free(*srkKey); goto done; } srkKeyContainer.pubKey.key = save; } #endif if ((result = mc_add_entry_init(SRK_TPM_HANDLE, SRK_TPM_HANDLE, &srkKeyContainer, &SRK_UUID))) { destroy_key_refs(&srkKeyContainer); LogError("Error creating SRK mem cache entry"); *srkKeySize = 0; free(*srkKey); } destroy_key_refs(&srkKeyContainer); } LogResult("TakeOwnership", result); done: auth_mgr_release_auth(ownerAuth, NULL, hContext); return result; }
TSS_RESULT secret_TakeOwnership(TSS_HKEY hEndorsementPubKey, TSS_HTPM hTPM, TSS_HKEY hKeySRK, TPM_AUTH * auth, UINT32 * encOwnerAuthLength, BYTE * encOwnerAuth, UINT32 * encSRKAuthLength, BYTE * encSRKAuth) { TSS_RESULT result; UINT32 endorsementKeySize; BYTE *endorsementKey; TSS_KEY dummyKey; UINT64 offset; TCPA_SECRET ownerSecret; TCPA_SECRET srkSecret; TCPA_DIGEST digest; TSS_HPOLICY hSrkPolicy; TSS_HPOLICY hOwnerPolicy; UINT32 srkKeyBlobLength; BYTE *srkKeyBlob; TSS_HCONTEXT tspContext; UINT32 ownerMode, srkMode; Trspi_HashCtx hashCtx; if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext))) return result; /************************************************* * First, get the policy objects and check them for how * to handle the secrets. If they cannot be found * or there is an error, then we must fail **************************************************/ /* First get the Owner Policy */ if ((result = obj_tpm_get_policy(hTPM, TSS_POLICY_USAGE, &hOwnerPolicy))) return result; /* Now get the SRK Policy */ if ((result = obj_rsakey_get_policy(hKeySRK, TSS_POLICY_USAGE, &hSrkPolicy, NULL))) return result; if ((result = obj_policy_get_mode(hOwnerPolicy, &ownerMode))) return result; if ((result = obj_policy_get_mode(hSrkPolicy, &srkMode))) return result; /* If the policy callback's aren't the same, that's an error if one is callback */ if (srkMode == TSS_SECRET_MODE_CALLBACK || ownerMode == TSS_SECRET_MODE_CALLBACK) { if (srkMode != TSS_SECRET_MODE_CALLBACK || ownerMode != TSS_SECRET_MODE_CALLBACK) { LogError("Policy callback modes for SRK policy and Owner policy differ."); return TSPERR(TSS_E_BAD_PARAMETER); } } if (ownerMode != TSS_SECRET_MODE_CALLBACK) { /* First, get the Endorsement Public Key for Encrypting */ if ((result = obj_rsakey_get_blob(hEndorsementPubKey, &endorsementKeySize, &endorsementKey))) return result; /* now stick it in a Key Structure */ offset = 0; if ((result = UnloadBlob_TSS_KEY(&offset, endorsementKey, &dummyKey))) { free_tspi(tspContext, endorsementKey); return result; } free_tspi(tspContext, endorsementKey); if ((result = obj_policy_get_secret(hOwnerPolicy, TR_SECRET_CTX_NEW, &ownerSecret))) { free(dummyKey.pubKey.key); free(dummyKey.algorithmParms.parms); return result; } if ((result = obj_policy_get_secret(hSrkPolicy, TR_SECRET_CTX_NEW, &srkSecret))) { free(dummyKey.pubKey.key); free(dummyKey.algorithmParms.parms); return result; } /* Encrypt the Owner, SRK Authorizations */ if ((result = Trspi_RSA_Encrypt(ownerSecret.authdata, 20, encOwnerAuth, encOwnerAuthLength, dummyKey.pubKey.key, dummyKey.pubKey.keyLength))) { free(dummyKey.pubKey.key); free(dummyKey.algorithmParms.parms); return result; } if ((result = Trspi_RSA_Encrypt(srkSecret.authdata, 20, encSRKAuth, encSRKAuthLength, dummyKey.pubKey.key, dummyKey.pubKey.keyLength))) { free(dummyKey.pubKey.key); free(dummyKey.algorithmParms.parms); return result; } free(dummyKey.pubKey.key); free(dummyKey.algorithmParms.parms); } else { *encOwnerAuthLength = 256; *encSRKAuthLength = 256; if ((result = obj_policy_do_takeowner(hOwnerPolicy, hTPM, hEndorsementPubKey, *encOwnerAuthLength, encOwnerAuth))) return result; } if ((result = obj_rsakey_get_blob(hKeySRK, &srkKeyBlobLength, &srkKeyBlob))) return result; /* Authorizatin Digest Calculation */ result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_TakeOwnership); result |= Trspi_Hash_UINT16(&hashCtx, TCPA_PID_OWNER); result |= Trspi_Hash_UINT32(&hashCtx, *encOwnerAuthLength); result |= Trspi_HashUpdate(&hashCtx, *encOwnerAuthLength, encOwnerAuth); result |= Trspi_Hash_UINT32(&hashCtx, *encSRKAuthLength); result |= Trspi_HashUpdate(&hashCtx, *encSRKAuthLength, encSRKAuth); result |= Trspi_HashUpdate(&hashCtx, srkKeyBlobLength, srkKeyBlob); free_tspi(tspContext, srkKeyBlob); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) return result; /* HMAC for the final digest */ if ((result = secret_PerformAuth_OIAP(hTPM, TPM_ORD_TakeOwnership, hOwnerPolicy, FALSE, &digest, auth))) return result; return TSS_SUCCESS; }
TSS_RESULT Tspi_Context_LoadKeyByBlob(TSS_HCONTEXT tspContext, /* in */ TSS_HKEY hUnwrappingKey, /* in */ UINT32 ulBlobLength, /* in */ BYTE * rgbBlobData, /* in */ TSS_HKEY * phKey) /* out */ { TPM_AUTH auth; UINT64 offset; TCPA_DIGEST digest; TSS_RESULT result; UINT32 keyslot; TSS_HPOLICY hPolicy; TCS_KEY_HANDLE tcsParentHandle, myTCSKeyHandle; TSS_KEY keyContainer; TSS_BOOL useAuth; TPM_AUTH *pAuth; TSS_FLAG initFlags; UINT16 realKeyBlobSize; TCPA_KEY_USAGE keyUsage; UINT32 pubLen; Trspi_HashCtx hashCtx; TPM_COMMAND_CODE ordinal; if (phKey == NULL || rgbBlobData == NULL ) return TSPERR(TSS_E_BAD_PARAMETER); if (!obj_is_rsakey(hUnwrappingKey)) return TSPERR(TSS_E_INVALID_HANDLE); if ((result = obj_context_get_loadkey_ordinal(tspContext, &ordinal))) return result; if ((result = obj_rsakey_get_tcs_handle(hUnwrappingKey, &tcsParentHandle))) return result; offset = 0; if ((result = UnloadBlob_TSS_KEY(&offset, rgbBlobData, &keyContainer))) return result; realKeyBlobSize = offset; pubLen = keyContainer.pubKey.keyLength; keyUsage = keyContainer.keyUsage; /* free these now, since they're not used below */ free_key_refs(&keyContainer); if ((result = obj_rsakey_get_policy(hUnwrappingKey, TSS_POLICY_USAGE, &hPolicy, &useAuth))) return result; if (useAuth) { /* Create the Authorization */ result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, ordinal); result |= Trspi_HashUpdate(&hashCtx, ulBlobLength, rgbBlobData); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) return result; if ((result = secret_PerformAuth_OIAP(hUnwrappingKey, ordinal, hPolicy, FALSE, &digest, &auth))) return result; pAuth = &auth; } else { pAuth = NULL; } if ((result = TCS_API(tspContext)->LoadKeyByBlob(tspContext, tcsParentHandle, ulBlobLength, rgbBlobData, pAuth, &myTCSKeyHandle, &keyslot))) return result; if (useAuth) { /* --- Validate return auth */ result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, result); result |= Trspi_Hash_UINT32(&hashCtx, ordinal); if (ordinal == TPM_ORD_LoadKey) result |= Trspi_Hash_UINT32(&hashCtx, keyslot); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) return result; if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, &auth))) return result; } /* --- Create a new Object */ initFlags = 0; if (pubLen == 0x100) initFlags |= TSS_KEY_SIZE_2048; else if (pubLen == 0x80) initFlags |= TSS_KEY_SIZE_1024; else if (pubLen == 0x40) initFlags |= TSS_KEY_SIZE_512; /* clear the key type field */ initFlags &= ~TSS_KEY_TYPE_MASK; if (keyUsage == TPM_KEY_STORAGE) initFlags |= TSS_KEY_TYPE_STORAGE; else initFlags |= TSS_KEY_TYPE_SIGNING; /* loading the blob will fix this back to what it should be. */ if ((result = obj_rsakey_add(tspContext, initFlags, phKey))) { LogDebug("Failed create object"); return TSPERR(TSS_E_INTERNAL_ERROR); } if ((result = obj_rsakey_set_tcpakey(*phKey,realKeyBlobSize, rgbBlobData))) { LogDebug("Key loaded but failed to setup the key object" "correctly"); return TSPERR(TSS_E_INTERNAL_ERROR); } return obj_rsakey_set_tcs_handle(*phKey, myTCSKeyHandle); }
TSS_RESULT Tspi_Key_WrapKey(TSS_HKEY hKey, /* in */ TSS_HKEY hWrappingKey, /* in */ TSS_HPCRS hPcrComposite) /* in, may be NULL */ { TSS_HPOLICY hUsePolicy, hMigPolicy; TCPA_SECRET usage, migration; TSS_RESULT result; BYTE *keyPrivBlob = NULL, *wrappingPubKey = NULL, *keyBlob = NULL; UINT32 keyPrivBlobLen, wrappingPubKeyLen, keyBlobLen; BYTE newPrivKey[214]; /* its not magic, see TPM 1.1b spec p.71 */ BYTE encPrivKey[256]; UINT32 newPrivKeyLen = 214, encPrivKeyLen = 256; UINT64 offset; TSS_KEY keyContainer; TCPA_DIGEST digest; TSS_HCONTEXT tspContext; Trspi_HashCtx hashCtx; if ((result = obj_rsakey_get_tsp_context(hKey, &tspContext))) return result; if (hPcrComposite) { if ((result = obj_rsakey_set_pcr_data(hKey, hPcrComposite))) return result; } /* get the key to be wrapped's private key */ if ((result = obj_rsakey_get_priv_blob(hKey, &keyPrivBlobLen, &keyPrivBlob))) goto done; /* get the key to be wrapped's blob */ if ((result = obj_rsakey_get_blob(hKey, &keyBlobLen, &keyBlob))) goto done; /* get the wrapping key's public key */ if ((result = obj_rsakey_get_modulus(hWrappingKey, &wrappingPubKeyLen, &wrappingPubKey))) goto done; /* get the key to be wrapped's usage policy */ if ((result = obj_rsakey_get_policy(hKey, TSS_POLICY_USAGE, &hUsePolicy, NULL))) goto done; if ((result = obj_rsakey_get_policy(hKey, TSS_POLICY_MIGRATION, &hMigPolicy, NULL))) goto done; if ((result = obj_policy_get_secret(hUsePolicy, TR_SECRET_CTX_NEW, &usage))) goto done; if ((result = obj_policy_get_secret(hMigPolicy, TR_SECRET_CTX_NEW, &migration))) goto done; memset(&keyContainer, 0, sizeof(TSS_KEY)); /* unload the key to be wrapped's blob */ offset = 0; if ((result = UnloadBlob_TSS_KEY(&offset, keyBlob, &keyContainer))) return result; /* load the key's attributes into an object and get its hash value */ result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Hash_TSS_PRIVKEY_DIGEST(&hashCtx, &keyContainer); if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) return result; free_key_refs(&keyContainer); /* create the plaintext private key blob */ offset = 0; Trspi_LoadBlob_BYTE(&offset, TCPA_PT_ASYM, newPrivKey); Trspi_LoadBlob(&offset, 20, newPrivKey, usage.authdata); Trspi_LoadBlob(&offset, 20, newPrivKey, migration.authdata); Trspi_LoadBlob(&offset, 20, newPrivKey, digest.digest); Trspi_LoadBlob_UINT32(&offset, keyPrivBlobLen, newPrivKey); Trspi_LoadBlob(&offset, keyPrivBlobLen, newPrivKey, keyPrivBlob); newPrivKeyLen = offset; /* encrypt the private key blob */ if ((result = Trspi_RSA_Encrypt(newPrivKey, newPrivKeyLen, encPrivKey, &encPrivKeyLen, wrappingPubKey, wrappingPubKeyLen))) goto done; /* set the new encrypted private key in the wrapped key object */ if ((result = obj_rsakey_set_privkey(hKey, FALSE, encPrivKeyLen, encPrivKey))) goto done; done: free_tspi(tspContext, keyPrivBlob); free_tspi(tspContext, keyBlob); free_tspi(tspContext, wrappingPubKey); return result; }
TSS_RESULT Tspi_Context_GetKeyByPublicInfo(TSS_HCONTEXT tspContext, /* in */ TSS_FLAG persistentStorageType, /* in */ TSS_ALGORITHM_ID algID, /* in */ UINT32 ulPublicInfoLength, /* in */ BYTE * rgbPublicInfo, /* in */ TSS_HKEY * phKey) /* out */ { TCPA_ALGORITHM_ID tcsAlgID; UINT32 keyBlobSize; BYTE *keyBlob; TSS_RESULT result; TSS_HKEY keyOutHandle; UINT32 flag = 0; TSS_KEY keyContainer; UINT64 offset; if (phKey == NULL) return TSPERR(TSS_E_BAD_PARAMETER); if (!obj_is_context(tspContext)) return TSPERR(TSS_E_INVALID_HANDLE); switch (algID) { case TSS_ALG_RSA: tcsAlgID = TCPA_ALG_RSA; break; default: LogError("Algorithm ID was not type RSA."); return TSPERR(TSS_E_BAD_PARAMETER); } if (persistentStorageType == TSS_PS_TYPE_SYSTEM) { if ((result = RPC_GetRegisteredKeyByPublicInfo(tspContext, tcsAlgID, ulPublicInfoLength, rgbPublicInfo, &keyBlobSize, &keyBlob))) return result; } else if (persistentStorageType == TSS_PS_TYPE_USER) { return ps_get_key_by_pub(tspContext, ulPublicInfoLength, rgbPublicInfo, phKey); } else return TSPERR(TSS_E_BAD_PARAMETER); /* need to setup the init flags of the create object based on * the size of the blob's pubkey */ offset = 0; if ((result = UnloadBlob_TSS_KEY(&offset, keyBlob, &keyContainer))) { free(keyBlob); return result; } /* begin setting up the key object */ switch (keyContainer.pubKey.keyLength) { case 16384/8: flag |= TSS_KEY_SIZE_16384; break; case 8192/8: flag |= TSS_KEY_SIZE_8192; break; case 4096/8: flag |= TSS_KEY_SIZE_4096; break; case 2048/8: flag |= TSS_KEY_SIZE_2048; break; case 1024/8: flag |= TSS_KEY_SIZE_1024; break; case 512/8: flag |= TSS_KEY_SIZE_512; break; default: LogError("Key was not a known keylength."); free(keyBlob); free_key_refs(&keyContainer); return TSPERR(TSS_E_INTERNAL_ERROR); } if (keyContainer.keyUsage == TPM_KEY_SIGNING) flag |= TSS_KEY_TYPE_SIGNING; else if (keyContainer.keyUsage == TPM_KEY_STORAGE) flag |= TSS_KEY_TYPE_STORAGE; else if (keyContainer.keyUsage == TPM_KEY_IDENTITY) flag |= TSS_KEY_TYPE_IDENTITY; else if (keyContainer.keyUsage == TPM_KEY_AUTHCHANGE) flag |= TSS_KEY_TYPE_AUTHCHANGE; else if (keyContainer.keyUsage == TPM_KEY_BIND) flag |= TSS_KEY_TYPE_BIND; else if (keyContainer.keyUsage == TPM_KEY_LEGACY) flag |= TSS_KEY_TYPE_LEGACY; if (keyContainer.authDataUsage == TPM_AUTH_NEVER) flag |= TSS_KEY_NO_AUTHORIZATION; else flag |= TSS_KEY_AUTHORIZATION; if (keyContainer.keyFlags & TPM_MIGRATABLE) flag |= TSS_KEY_MIGRATABLE; else flag |= TSS_KEY_NOT_MIGRATABLE; if (keyContainer.keyFlags & TPM_VOLATILE) flag |= TSS_KEY_VOLATILE; else flag |= TSS_KEY_NON_VOLATILE; #ifdef TSS_BUILD_CMK if (keyContainer.keyFlags & TPM_MIGRATEAUTHORITY) flag |= TSS_KEY_CERTIFIED_MIGRATABLE; else flag |= TSS_KEY_NOT_CERTIFIED_MIGRATABLE; #endif /* Create a new Key Object */ if ((result = obj_rsakey_add(tspContext, flag, &keyOutHandle))) { free(keyBlob); free_key_refs(&keyContainer); return result; } /* Stick the info into this net KeyObject */ if ((result = obj_rsakey_set_tcpakey(keyOutHandle, keyBlobSize, keyBlob))) { free(keyBlob); free_key_refs(&keyContainer); return result; } free(keyBlob); free_key_refs(&keyContainer); *phKey = keyOutHandle; return TSS_SUCCESS; }
/* * read the PS file pointed to by fd and create a cache based on it */ int init_disk_cache(int fd) { UINT32 num_keys = get_num_keys_in_file(fd); UINT16 i; UINT64 tmp_offset; int rc = 0, offset; struct key_disk_cache *tmp, *prev = NULL; BYTE srk_blob[2048]; TSS_KEY srk_key; #ifdef TSS_DEBUG int valid_keys = 0; #endif MUTEX_LOCK(disk_cache_lock); if (num_keys == 0) { key_disk_cache_head = NULL; MUTEX_UNLOCK(disk_cache_lock); return 0; } else { key_disk_cache_head = tmp = calloc(1, sizeof(struct key_disk_cache)); if (tmp == NULL) { LogError("malloc of %zd bytes failed.", sizeof(struct key_disk_cache)); rc = -1; goto err_exit; } } /* make sure the file pointer is where we expect, just after the number * of keys on disk at the head of the file */ offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET); if (offset == ((off_t) - 1)) { LogError("lseek: %s", strerror(errno)); rc = -1; goto err_exit; } for (i=0; i<num_keys; i++) { offset = lseek(fd, 0, SEEK_CUR); if (offset == ((off_t) - 1)) { LogError("lseek: %s", strerror(errno)); rc = -1; goto err_exit; } tmp->offset = offset; #ifdef TSS_DEBUG if (offset == 0) LogDebug("Storing key with file offset==0!!!"); #endif /* read UUID */ if ((rc = read_data(fd, (void *)&tmp->uuid, sizeof(TSS_UUID)))) { LogError("%s", __FUNCTION__); goto err_exit; } /* read parent UUID */ if ((rc = read_data(fd, (void *)&tmp->parent_uuid, sizeof(TSS_UUID)))) { LogError("%s", __FUNCTION__); goto err_exit; } /* pub data size */ if ((rc = read_data(fd, &tmp->pub_data_size, sizeof(UINT16)))) { LogError("%s", __FUNCTION__); goto err_exit; } tmp->pub_data_size = LE_16(tmp->pub_data_size); DBG_ASSERT(tmp->pub_data_size <= 2048 && tmp->pub_data_size > 0); /* blob size */ if ((rc = read_data(fd, &tmp->blob_size, sizeof(UINT16)))) { LogError("%s", __FUNCTION__); goto err_exit; } tmp->blob_size = LE_16(tmp->blob_size); DBG_ASSERT(tmp->blob_size <= 4096 && tmp->blob_size > 0); /* vendor data size */ if ((rc = read_data(fd, &tmp->vendor_data_size, sizeof(UINT32)))) { LogError("%s", __FUNCTION__); goto err_exit; } tmp->vendor_data_size = LE_32(tmp->vendor_data_size); /* cache flags */ if ((rc = read_data(fd, &tmp->flags, sizeof(UINT16)))) { LogError("%s", __FUNCTION__); goto err_exit; } tmp->flags = LE_16(tmp->flags); #ifdef TSS_DEBUG if (tmp->flags & CACHE_FLAG_VALID) valid_keys++; #endif /* fast forward over the pub key */ offset = lseek(fd, tmp->pub_data_size, SEEK_CUR); if (offset == ((off_t) - 1)) { LogError("lseek: %s", strerror(errno)); rc = -1; goto err_exit; } /* if this is the SRK, load it into memory, since its already loaded in * the chip */ if (!memcmp(&SRK_UUID, &tmp->uuid, sizeof(TSS_UUID))) { /* read SRK blob from disk */ if ((rc = read_data(fd, srk_blob, tmp->blob_size))) { LogError("%s", __FUNCTION__); goto err_exit; } tmp_offset = 0; if ((rc = UnloadBlob_TSS_KEY(&tmp_offset, srk_blob, &srk_key))) goto err_exit; /* add to the mem cache */ if ((rc = mc_add_entry_init(SRK_TPM_HANDLE, SRK_TPM_HANDLE, &srk_key, &SRK_UUID))) { LogError("Error adding SRK to mem cache."); destroy_key_refs(&srk_key); goto err_exit; } destroy_key_refs(&srk_key); } else { /* fast forward over the blob */ offset = lseek(fd, tmp->blob_size, SEEK_CUR); if (offset == ((off_t) - 1)) { LogError("lseek: %s", strerror(errno)); rc = -1; goto err_exit; } /* fast forward over the vendor data */ offset = lseek(fd, tmp->vendor_data_size, SEEK_CUR); if (offset == ((off_t) - 1)) { LogError("lseek: %s", strerror(errno)); rc = -1; goto err_exit; } } tmp->next = calloc(1, sizeof(struct key_disk_cache)); if (tmp->next == NULL) { LogError("malloc of %zd bytes failed.", sizeof(struct key_disk_cache)); rc = -1; goto err_exit; } prev = tmp; tmp = tmp->next; } /* delete the dangling, unfilled cache entry */ free(tmp); prev->next = NULL; rc = 0; LogDebug("%s: found %d valid key(s) on disk.\n", __FUNCTION__, valid_keys); err_exit: MUTEX_UNLOCK(disk_cache_lock); return rc; }
/* * disk store format: * * TrouSerS 0.2.1+ * Version 1: cached? * [BYTE PS version = '\1'] * [UINT32 num_keys_on_disk ] * [TSS_UUID uuid0 ] yes * [TSS_UUID uuid_parent0 ] yes * [UINT16 pub_data_size0 ] yes * [UINT16 blob_size0 ] yes * [UINT32 vendor_data_size0] yes * [UINT16 cache_flags0 ] yes * [BYTE[] pub_data0 ] * [BYTE[] blob0 ] * [BYTE[] vendor_data0 ] * [...] * */ TSS_RESULT psfile_write_key(int fd, TSS_UUID *uuid, TSS_UUID *parent_uuid, UINT32 parent_ps, BYTE *key_blob, UINT16 key_blob_size) { TSS_RESULT result; TSS_KEY key; UINT32 zero = 0; UINT64 offset; UINT16 pub_key_size, cache_flags = 0; struct stat stat_buf; int rc, file_offset; /* leaving the cache flag for parent ps type as 0 implies TSS_PS_TYPE_USER */ if (parent_ps == TSS_PS_TYPE_SYSTEM) cache_flags |= CACHE_FLAG_PARENT_PS_SYSTEM; if ((rc = fstat(fd, &stat_buf)) == -1) { LogDebugFn("stat failed: %s", strerror(errno)); return TSPERR(TSS_E_INTERNAL_ERROR); } file_offset = stat_buf.st_size; if (file_offset < (int)TSSPS_KEYS_OFFSET) { if ((result = psfile_write_key_header(fd))) return result; file_offset = TSSPS_KEYS_OFFSET; } rc = lseek(fd, file_offset, SEEK_SET); if (rc == ((off_t)-1)) { LogDebug("lseek: %s", strerror(errno)); return TSPERR(TSS_E_INTERNAL_ERROR); } /* Unload the blob to get the public key */ offset = 0; if ((result = UnloadBlob_TSS_KEY(&offset, key_blob, &key))) return result; pub_key_size = key.pubKey.keyLength; /* [TSS_UUID uuid0 ] yes */ if ((result = write_data(fd, (void *)uuid, sizeof(TSS_UUID)))) { LogDebug("%s", __FUNCTION__); goto done; } /* [TSS_UUID uuid_parent0 ] yes */ if ((result = write_data(fd, (void *)parent_uuid, sizeof(TSS_UUID)))) { LogDebug("%s", __FUNCTION__); goto done; } /* [UINT16 pub_data_size0 ] yes */ pub_key_size = LE_16(pub_key_size); if ((result = write_data(fd, &pub_key_size, sizeof(UINT16)))) { LogDebug("%s", __FUNCTION__); goto done; } pub_key_size = LE_16(pub_key_size); /* [UINT16 blob_size0 ] yes */ key_blob_size = LE_16(key_blob_size); if ((result = write_data(fd, &key_blob_size, sizeof(UINT16)))) { LogDebug("%s", __FUNCTION__); goto done; } key_blob_size = LE_16(key_blob_size); /* [UINT32 vendor_data_size0 ] yes */ if ((result = write_data(fd, &zero, sizeof(UINT32)))) { LogDebug("%s", __FUNCTION__); goto done; } /* [UINT16 cache_flags0 ] yes */ cache_flags = LE_16(cache_flags); if ((result = write_data(fd, &cache_flags, sizeof(UINT16)))) { LogDebug("%s", __FUNCTION__); goto done; } cache_flags = LE_16(cache_flags); /* [BYTE[] pub_data0 ] no */ if ((result = write_data(fd, (void *)key.pubKey.key, pub_key_size))) { LogDebug("%s", __FUNCTION__); goto done; } /* [BYTE[] blob0 ] no */ if ((result = write_data(fd, (void *)key_blob, key_blob_size))) { LogDebug("%s", __FUNCTION__); goto done; } if ((result = psfile_change_num_keys(fd, TSS_PSFILE_INCREMENT_NUM_KEYS))) { LogDebug("%s", __FUNCTION__); goto done; } done: free_key_refs(&key); return result; }