TPM_RESULT TPM_ChangeAuth(TPM_KEY_HANDLE parentHandle, TPM_PROTOCOL_ID protocolID, TPM_ENCAUTH *newAuth, TPM_ENTITY_TYPE entityType, UINT32 encDataSize, BYTE *encData, TPM_AUTH *auth1, TPM_AUTH *auth2, UINT32 *outDataSize, BYTE **outData) { TPM_RESULT res; TPM_KEY_DATA *parent; TPM_SESSION_DATA *session; TPM_SECRET plainAuth; info("TPM_ChangeAuth()"); /* get parent key */ parent = tpm_get_key(parentHandle); if (parent == NULL) return TPM_INVALID_KEYHANDLE; /* verify entity authorization */ auth2->continueAuthSession = FALSE; session = tpm_get_auth(auth2->authHandle); if (session->type != TPM_ST_OIAP) return TPM_BAD_MODE; /* verify parent authorization */ res = tpm_verify_auth(auth1, parent->usageAuth, parentHandle); if (res != TPM_SUCCESS) return res; auth1->continueAuthSession = FALSE; session = tpm_get_auth(auth1->authHandle); if (session->type != TPM_ST_OSAP) return TPM_BAD_MODE; /* decrypt auth */ tpm_decrypt_auth_secret(*newAuth, session->sharedSecret, &session->lastNonceEven, plainAuth); /* decrypt the entity, replace authData, and encrypt it again */ if (entityType == TPM_ET_DATA) { TPM_SEALED_DATA seal; BYTE *seal_buf; /* decrypt entity */ if (decrypt_sealed_data(parent, encData, encDataSize, &seal, &seal_buf)) return TPM_DECRYPT_ERROR; /* verify auth2 */ res = tpm_verify_auth(auth2, seal.authData, TPM_INVALID_HANDLE); if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res; /* change authData and use it also for auth2 */ memcpy(seal.authData, plainAuth, sizeof(TPM_SECRET)); /* encrypt entity */ *outDataSize = parent->key.size >> 3; *outData = tpm_malloc(*outDataSize); if (encrypt_sealed_data(parent, &seal, *outData, outDataSize)) { tpm_free(encData); tpm_free(seal_buf); return TPM_ENCRYPT_ERROR; } tpm_free(seal_buf); } else if (entityType == TPM_ET_KEY) {
TPM_RESULT TPM_SaveContext(TPM_HANDLE handle, TPM_RESOURCE_TYPE resourceType, const BYTE label[16], UINT32 *contextSize, TPM_CONTEXT_BLOB *contextBlob) { TPM_CONTEXT_SENSITIVE context; TPM_SESSION_DATA *session = NULL; TPM_DAA_SESSION_DATA *sessionDAA = NULL; TPM_KEY_DATA *key = NULL; int i = 0; info("TPM_SaveContext() resourceType = %08x", resourceType); /* setup context data */ context.tag = TPM_TAG_CONTEXT_SENSITIVE; context.resourceType = resourceType; if (resourceType == TPM_RT_AUTH || resourceType == TPM_RT_TRANS) { session = (resourceType == TPM_RT_AUTH) ? tpm_get_auth(handle) : tpm_get_transport(handle); if (session == NULL) return TPM_INVALID_RESOURCE; /* store session data */ memcpy(&context.internalData.session, session, sizeof(TPM_SESSION_DATA)); context.internalSize = sizeof_TPM_SESSION_DATA((*session)); /* set context nonce */ memcpy(&context.contextNonce, &tpmData.stany.data.contextNonceSession, sizeof(TPM_NONCE)); } else if (resourceType == TPM_RT_KEY) { key = tpm_get_key(handle); debug("resourceType = TPM_RT_KEY, handle = %08x, key = %p", handle, key); if (key == NULL) return TPM_INVALID_RESOURCE; if (key->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) return TPM_OWNER_CONTROL; /* store key data (shallow copy is ok) */ memcpy(&context.internalData.key, key, sizeof(TPM_KEY_DATA)); context.internalSize = sizeof_TPM_KEY_DATA((*key)); /* set context nonce */ memcpy(&context.contextNonce, &tpmData.stclear.data.contextNonceKey, sizeof(TPM_NONCE)); } else if (resourceType == TPM_RT_DAA_TPM) { sessionDAA = tpm_get_daa(handle); if (sessionDAA == NULL) return TPM_INVALID_RESOURCE; /* store sessionDAA data */ memcpy(&context.internalData.sessionDAA, sessionDAA, sizeof(TPM_DAA_SESSION_DATA)); context.internalSize = sizeof(TPM_DAA_SESSION_DATA); /* set context nonce */ memcpy(&context.contextNonce, &tpmData.stany.data.contextNonceSession, sizeof(TPM_NONCE)); } else { return TPM_INVALID_RESOURCE; } /* setup context blob */ contextBlob->tag = TPM_TAG_CONTEXTBLOB; contextBlob->resourceType = resourceType; contextBlob->handle = handle; memset(&contextBlob->integrityDigest, 0, sizeof(TPM_DIGEST)); memcpy(contextBlob->label, label, sizeof(contextBlob->label)); contextBlob->additionalSize = TPM_SYM_KEY_SIZE; contextBlob->additionalData = tpm_malloc(contextBlob->additionalSize); if (contextBlob->additionalData == NULL) return TPM_FAIL; tpm_get_random_bytes(contextBlob->additionalData, contextBlob->additionalSize); /* increment context counter */ if (resourceType == TPM_RT_KEY) { contextBlob->contextCount = 0; } else { if (tpmData.stany.data.contextCount >= 0xfffffffc) { tpm_free(contextBlob->additionalData); return TPM_TOOMANYCONTEXTS; } contextBlob->contextCount = ++tpmData.stany.data.contextCount; for (i = 0; i < TPM_MAX_SESSION_LIST; i++) { if (tpmData.stany.data.contextList[i] == 0) break; } if (i >= TPM_MAX_SESSION_LIST) { tpm_free(contextBlob->additionalData); return TPM_NOCONTEXTSPACE; } tpmData.stany.data.contextCount++; tpmData.stany.data.contextList[i] = tpmData.stany.data.contextCount; contextBlob->contextCount = tpmData.stany.data.contextCount; } debug("context counter = %d", tpmData.stany.data.contextCount); /* encrypt sensitive data */ if (encrypt_context(contextBlob->additionalData, contextBlob->additionalSize, &context, &contextBlob->sensitiveData, &contextBlob->sensitiveSize)) { tpm_free(contextBlob->additionalData); return TPM_ENCRYPT_ERROR; } /* compute context digest */ if (compute_context_digest(contextBlob, &contextBlob->integrityDigest)) { tpm_free(contextBlob->additionalData); return TPM_FAIL; } *contextSize = sizeof_TPM_CONTEXT_BLOB((*contextBlob)); if (resourceType != TPM_RT_KEY) { /* The TPM MUST invalidate all information regarding the resource * except for information needed for reloading. */ if (resourceType != TPM_RT_DAA_TPM) session->type = TPM_ST_INVALID; else { memset(sessionDAA, 0, sizeof(TPM_DAA_SESSION_DATA)); sessionDAA->type = TPM_ST_INVALID; tpmData.stany.data.currentDAA = 0; } } return TPM_SUCCESS; }
TPM_RESULT TPM_TakeOwnership(TPM_PROTOCOL_ID protocolID, UINT32 encOwnerAuthSize, BYTE *encOwnerAuth, UINT32 encSrkAuthSize, BYTE *encSrkAuth, TPM_KEY *srkParams, TPM_AUTH *auth1, TPM_KEY *srkPub) { TPM_RESULT res; tpm_rsa_private_key_t *ek = &tpmData.permanent.data.endorsementKey; TPM_KEY_DATA *srk = &tpmData.permanent.data.srk; size_t buf_size = ek->size >> 3; BYTE buf[buf_size]; info("TPM_TakeOwnership()"); if (!ek->size) return TPM_NO_ENDORSEMENT; if (protocolID != TPM_PID_OWNER) return TPM_BAD_PARAMETER; if (tpmData.permanent.flags.owned) return TPM_OWNER_SET; if (!tpmData.permanent.flags.ownership) return TPM_INSTALL_DISABLED; /* decrypt ownerAuth */ if (tpm_rsa_decrypt(ek, RSA_ES_OAEP_SHA1, encOwnerAuth, encOwnerAuthSize, buf, &buf_size) != 0) return TPM_DECRYPT_ERROR; if (buf_size != sizeof(TPM_SECRET)) return TPM_BAD_KEY_PROPERTY; memcpy(tpmData.permanent.data.ownerAuth, buf, buf_size); /* verify authorization */ res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER); if (res != TPM_SUCCESS) return res; if (tpm_get_auth(auth1->authHandle)->type != TPM_ST_OIAP) return TPM_AUTHFAIL; /* reset srk and decrypt srkAuth */ memset(srk, 0, sizeof(*srk)); if (tpm_rsa_decrypt(ek, RSA_ES_OAEP_SHA1, encSrkAuth, encSrkAuthSize, buf, &buf_size) != 0) return TPM_DECRYPT_ERROR; if (buf_size != sizeof(TPM_SECRET)) return TPM_BAD_KEY_PROPERTY; memcpy(srk->usageAuth, buf, buf_size); /* validate SRK parameters */ if (srkParams->keyFlags & TPM_KEY_FLAG_MIGRATABLE || srkParams->keyUsage != TPM_KEY_STORAGE) return TPM_INVALID_KEYUSAGE; if (srkParams->algorithmParms.algorithmID != TPM_ALG_RSA || srkParams->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1 || srkParams->algorithmParms.sigScheme != TPM_SS_NONE || srkParams->algorithmParms.parmSize == 0 || srkParams->algorithmParms.parms.rsa.keyLength != 2048 || srkParams->algorithmParms.parms.rsa.numPrimes != 2 || srkParams->algorithmParms.parms.rsa.exponentSize != 0 || srkParams->PCRInfoSize != 0) return TPM_BAD_KEY_PROPERTY; /* setup and generate SRK */ srk->keyFlags = srkParams->keyFlags; srk->keyFlags |= TPM_KEY_FLAG_PCR_IGNORE; srk->keyFlags &= ~TPM_KEY_FLAG_HAS_PCR; srk->keyUsage = srkParams->keyUsage; srk->encScheme = srkParams->algorithmParms.encScheme; srk->sigScheme = srkParams->algorithmParms.sigScheme; srk->authDataUsage = srkParams->authDataUsage; debug("srk->authDataUsage = %02x", srk->authDataUsage); srk->parentPCRStatus = FALSE; srkParams->algorithmParms.parms.rsa.keyLength = 2048; if (tpm_rsa_generate_key(&srk->key, srkParams->algorithmParms.parms.rsa.keyLength)) return TPM_FAIL; srk->payload = TPM_PT_ASYM; /* generate context, delegate, and DAA key */ tpm_get_random_bytes(tpmData.permanent.data.contextKey, sizeof(tpmData.permanent.data.contextKey)); tpm_get_random_bytes(tpmData.permanent.data.delegateKey, sizeof(tpmData.permanent.data.delegateKey)); tpm_get_random_bytes(tpmData.permanent.data.daaKey, sizeof(tpmData.permanent.data.daaKey)); /* export SRK */ memcpy(srkPub, srkParams, sizeof(TPM_KEY)); srkPub->pubKey.keyLength = srk->key.size >> 3; srkPub->pubKey.key = tpm_malloc(srkPub->pubKey.keyLength); if (srkPub->pubKey.key == NULL) { tpm_rsa_release_private_key(&srk->key); srk->payload = TPM_PT_NONE; return TPM_FAIL; } tpm_rsa_export_modulus(&srk->key, srkPub->pubKey.key, NULL); /* setup tpmProof/daaProof and set state to owned */ tpm_get_random_bytes(tpmData.permanent.data.tpmProof.nonce, sizeof(tpmData.permanent.data.tpmProof.nonce)); tpm_get_random_bytes(tpmData.permanent.data.daaProof.nonce, sizeof(tpmData.permanent.data.daaProof.nonce)); tpmData.permanent.flags.readPubek = FALSE; tpmData.permanent.flags.owned = TRUE; return TPM_SUCCESS; }
TPM_RESULT TPM_CreateMigrationBlob(TPM_KEY_HANDLE parentHandle, TPM_MIGRATE_SCHEME migrationType, TPM_MIGRATIONKEYAUTH *migrationKeyAuth, UINT32 encDataSize, BYTE *encData, TPM_AUTH *auth1, TPM_AUTH *auth2, UINT32 *randomSize, BYTE **random, UINT32 *outDataSize, BYTE **outData) { TPM_RESULT res; TPM_KEY_DATA *parent; TPM_SESSION_DATA *session; BYTE *key_buf; UINT32 key_buf_size; TPM_STORE_ASYMKEY store; TPM_PUBKEY_DATA key; info("TPM_CreateMigrationBlob()"); /* get parent key */ parent = tpm_get_key(parentHandle); if (parent == NULL) return TPM_INVALID_KEYHANDLE; /* verify parent authorization */ res = tpm_verify_auth(auth1, parent->usageAuth, parentHandle); if (res != TPM_SUCCESS) return res; session = tpm_get_auth(auth2->authHandle); if (session == NULL || session->type != TPM_ST_OIAP) return TPM_AUTHFAIL; /* verify key properties */ if (parent->keyUsage != TPM_KEY_STORAGE) return TPM_INVALID_KEYUSAGE; /* decrypt private key */ if (tpm_decrypt_private_key(parent, encData, encDataSize, &store, &key_buf, &key_buf_size) != 0) { return TPM_DECRYPT_ERROR; } if (store.payload != TPM_PT_ASYM) { tpm_free(key_buf); return TPM_DECRYPT_ERROR; } debug("key size: %d / %d", store.privKey.keyLength, key_buf_size); /* verify migration authorization */ res = tpm_verify_auth(auth2, store.migrationAuth, TPM_INVALID_HANDLE); if (res != TPM_SUCCESS) { tpm_free(key_buf); return TPM_MIGRATEFAIL; } if (tpm_verify_migration_digest(migrationKeyAuth, &tpmData.permanent.data.tpmProof)) { debug("tpm_verify_migration_digest() failed"); tpm_free(key_buf); return TPM_MIGRATEFAIL; } debug("migration authorization is valid."); /* set public key */ if (tpm_setup_pubkey_data(&migrationKeyAuth->migrationKey, &key) != 0) { debug("tpm_setup_pubkey() failed"); tpm_free(key_buf); return TPM_FAIL; } /* perform migration */ if (migrationType == TPM_MS_REWRAP) { /* re-encrypt raw key data */ debug("migrationType = TPM_MS_REWRAP"); *random = NULL; *randomSize = 0; *outDataSize = key.key.size >> 3; *outData = tpm_malloc(*outDataSize); if (*outData == NULL) { free_TPM_PUBKEY_DATA(key); tpm_free(*outData); tpm_free(key_buf); return TPM_FAIL; } if (tpm_encrypt_public(&key, key_buf, key_buf_size, *outData, outDataSize) != 0) { free_TPM_PUBKEY_DATA(key); tpm_free(*outData); tpm_free(key_buf); return TPM_ENCRYPT_ERROR; } } else if (migrationType == TPM_MS_MIGRATE) {