static void compute_key_digest(TPM_REQUEST *req, TPM_DIGEST *digest) { tpm_sha1_ctx_t ctx; TPM_HANDLE h1, h2; TPM_KEY_DATA *k1, *k2; BYTE *ptr; UINT32 len, offset = tpm_get_in_param_offset(req->ordinal); /* handle some exceptions */ if (req->ordinal == TPM_ORD_FlushSpecific) offset = 0; else if (req->ordinal == TPM_ORD_OwnerReadInternalPub) offset = 4; /* compute public key digests */ if (offset == 0) { debug("no handles"); memset(digest, 0, sizeof(TPM_DIGEST)); } else if (offset == 4) { debug("one handle"); ptr = req->param; len = 4; tpm_unmarshal_TPM_HANDLE(&ptr, &len, &h1); k1 = tpm_get_key(h1); if (k1 != NULL && tpm_compute_key_data_digest(k1, digest) == 0) { debug("key found"); /* compute outer hash */ tpm_sha1_init(&ctx); tpm_sha1_update(&ctx, digest->digest, sizeof(digest->digest)); tpm_sha1_final(&ctx, digest->digest); } else { memset(digest, 0, sizeof(TPM_DIGEST)); } } else if (offset == 8) { TPM_DIGEST digest2; debug("two handles"); ptr = req->param; len = 8; tpm_unmarshal_TPM_HANDLE(&ptr, &len, &h1); tpm_unmarshal_TPM_HANDLE(&ptr, &len, &h2); k1 = tpm_get_key(h1); k2 = tpm_get_key(h2); if (k1 != NULL && tpm_compute_key_data_digest(k1, digest) == 0 && k2 != NULL && tpm_compute_key_data_digest(k2, &digest2) == 0) { debug("two keys found"); /* compute outer hash */ tpm_sha1_init(&ctx); tpm_sha1_update(&ctx, digest->digest, sizeof(digest->digest)); tpm_sha1_update(&ctx, digest2.digest, sizeof(digest2.digest)); tpm_sha1_final(&ctx, digest->digest); } else { memset(digest, 0, sizeof(TPM_DIGEST)); } } else { memset(digest, 0, sizeof(TPM_DIGEST)); } }
TPM_RESULT TPM_ReleaseTransportSigned(TPM_KEY_HANDLE keyHandle, TPM_NONCE *antiReplay, TPM_AUTH *auth1, TPM_AUTH *auth2, TPM_MODIFIER_INDICATOR *locality, TPM_CURRENT_TICKS *currentTicks, UINT32 *sigSize, BYTE **sig) { TPM_RESULT res; TPM_KEY_DATA *key; TPM_SESSION_DATA *session; BYTE buf[30 + 20]; info("TPM_ReleaseTransportSigned()"); /* get key */ key = tpm_get_key(keyHandle); if (key == NULL) return TPM_INVALID_KEYHANDLE; /* verify authorization */ if (auth2->authHandle != TPM_INVALID_HANDLE || key->authDataUsage != TPM_AUTH_NEVER) { res = tpm_verify_auth(auth1, key->usageAuth, keyHandle); if (res != TPM_SUCCESS) return res; session = tpm_get_transport(auth2->authHandle); if (session == NULL) return TPM_INVALID_AUTHHANDLE; res = tpm_verify_auth(auth2, session->transInternal.authData, TPM_INVALID_HANDLE); if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res; } else { session = tpm_get_transport(auth1->authHandle); if (session == NULL) return TPM_INVALID_AUTHHANDLE; res = tpm_verify_auth(auth1, session->transInternal.authData, TPM_INVALID_HANDLE); if (res != TPM_SUCCESS) return res; } /* invalidate transport session */ auth1->continueAuthSession = FALSE; /* logging must be enabled */ if (!(session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_LOG)) return TPM_BAD_MODE; *locality = tpmData.stany.flags.localityModifier; memcpy(currentTicks, &tpmData.stany.data.currentTicks, sizeof(TPM_CURRENT_TICKS)); transport_log_out(auth1->digest, &session->transInternal.transDigest); /* setup a TPM_SIGN_INFO structure */ memcpy(&buf[0], (uint8_t*)"\x00\x05TRAN", 6); memcpy(&buf[6], antiReplay->nonce, 20); memcpy(&buf[26], (uint8_t*)"\x00\x00\x00\x14", 4); memcpy(&buf[30], session->transInternal.transDigest.digest, 20); /* sign info structure */ if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) { tpm_sha1_ctx_t ctx; debug("TPM_SS_RSASSAPKCS1v15_SHA1"); tpm_sha1_init(&ctx); tpm_sha1_update(&ctx, buf, sizeof(buf)); tpm_sha1_final(&ctx, buf); res = tpm_sign(key, auth1, FALSE, buf, SHA1_DIGEST_LENGTH, sig, sigSize); } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO) { debug("TPM_SS_RSASSAPKCS1v15_INFO"); res = tpm_sign(key, auth1, TRUE, buf, sizeof(buf), sig, sigSize); } else { debug("unsupported signature scheme: %02x", key->sigScheme); res = TPM_INVALID_KEYUSAGE; } return res; }
TPM_RESULT TPM_KeyControlOwner(TPM_KEY_HANDLE keyHandle, UINT32 bitName, BOOL bitValue, TPM_AUTH *auth1) { TPM_RESULT res; TPM_KEY_DATA *key; info("TPM_KeyControlOwner()"); /* get key */ key = tpm_get_key(keyHandle); if (key == NULL) return TPM_INVALID_KEYHANDLE; /* verify authorization */ res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER); if (res != TPM_SUCCESS) return res; /* get bit name */ switch (bitName) { case TPM_KEY_CONTROL_OWNER_EVICT: if (bitValue) { int i, num = 0; for (i = 0; i < TPM_MAX_KEYS; i++) { if (!tpmData.permanent.data.keys[i].valid || !(tpmData.permanent.data.keys[i].keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) num++; } if (num < 2) return TPM_NOSPACE; if (key->parentPCRStatus || (key->keyFlags & TPM_KEY_FLAG_VOLATILE)) return TPM_BAD_PARAMETER; key->keyControl |= TPM_KEY_CONTROL_OWNER_EVICT; } else { key->keyControl &= ~TPM_KEY_CONTROL_OWNER_EVICT; } return TPM_SUCCESS; default: return TPM_BAD_PARAMETER; } }
TPM_RESULT TPM_KeyControlOwner(TPM_KEY_HANDLE keyHandle, TPM_PUBKEY pubKey, UINT32 bitName, BOOL bitValue, TPM_AUTH *auth1) { TPM_RESULT res; TPM_KEY_DATA *key; TPM_PUBKEY pubKey2; TPM_DIGEST keyDigest, keyDigest2; info("TPM_KeyControlOwner()"); /* get key */ key = tpm_get_key(keyHandle); if (key == NULL) return TPM_INVALID_KEYHANDLE; /* verify authorization */ res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER); if (res != TPM_SUCCESS) return res; /* verify public key */ if (tpm_compute_pubkey_digest(&pubKey, &keyDigest)) { debug("tpm_compute_pubkey_digest() failed"); return TPM_FAIL; } if (tpm_extract_pubkey(key, &pubKey2)) { debug("tpm_extraxt_pubkey() failed."); return TPM_FAIL; } if (tpm_compute_pubkey_digest(&pubKey2, &keyDigest2)) { debug("tpm_compute_pubkey_digest() failed"); free_TPM_PUBKEY(pubKey2); return TPM_FAIL; } free_TPM_PUBKEY(pubKey2); if (memcmp(&keyDigest, &keyDigest2, sizeof(TPM_DIGEST)) != 0) return TPM_BAD_PARAMETER; /* get bit name */ debug("bitName = %d", bitName); if (bitName & TPM_KEY_CONTROL_OWNER_EVICT) { if (bitValue) { int i, num = 0; for (i = 0; i < TPM_MAX_KEYS; i++) { if (!tpmData.permanent.data.keys[i].payload || !(tpmData.permanent.data.keys[i].keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) num++; } if (num < 2) return TPM_NOSPACE; if (key->parentPCRStatus || (key->keyFlags & TPM_KEY_FLAG_VOLATILE)) return TPM_BAD_PARAMETER; key->keyControl |= TPM_KEY_CONTROL_OWNER_EVICT; } else { key->keyControl &= ~TPM_KEY_CONTROL_OWNER_EVICT; } } else { return TPM_BAD_MODE; } return TPM_SUCCESS; }
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_EstablishTransport(TPM_KEY_HANDLE encHandle, TPM_TRANSPORT_PUBLIC *transPublic, UINT32 secretSize, BYTE *secret, TPM_AUTH *auth1, TPM_TRANSHANDLE *transHandle, TPM_MODIFIER_INDICATOR *locality, TPM_CURRENT_TICKS *currentTicks, TPM_NONCE *transNonceEven) { TPM_RESULT res; TPM_KEY_DATA *key; TPM_TRANSPORT_AUTH trans_auth; TPM_SESSION_DATA *session; info("TPM_EstablishTransport()"); /* setup authorization data */ if (encHandle == TPM_KH_TRANSPORT) { if (auth1->authHandle != TPM_INVALID_HANDLE) return TPM_BADTAG; if (transPublic->transAttributes & TPM_TRANSPORT_ENCRYPT) return TPM_BAD_SCHEME; if (secretSize != 20) return TPM_BAD_PARAM_SIZE; memcpy(trans_auth.authData, secret, 20); } else { /* get key and verify its usage */ key = tpm_get_key(encHandle); if (key == NULL) return TPM_INVALID_KEYHANDLE; if (key->keyUsage != TPM_KEY_STORAGE && key->keyUsage != TPM_KEY_LEGACY) return TPM_INVALID_KEYUSAGE; /* verify authorization */ if (key->authDataUsage != TPM_AUTH_NEVER) { res = tpm_verify_auth(auth1, key->usageAuth, encHandle); if (res != TPM_SUCCESS) return res; if (decrypt_transport_auth(key, secret, secretSize, &trans_auth)) return TPM_DECRYPT_ERROR; } } /* check whether the transport has to be encrypted */ if (transPublic->transAttributes & TPM_TRANSPORT_ENCRYPT) { if (tpmData.permanent.flags.FIPS && transPublic->algID == TPM_ALG_MGF1) return TPM_INAPPROPRIATE_ENC; /* until now, only MGF1 is supported */ if (transPublic->algID != TPM_ALG_MGF1) return TPM_BAD_KEY_PROPERTY; } /* initialize transport session */ tpm_get_random_bytes(transNonceEven->nonce, sizeof(transNonceEven->nonce)); *transHandle = tpm_get_free_session(TPM_ST_TRANSPORT); session = tpm_get_transport(*transHandle); if (session == NULL) return TPM_RESOURCES; session->transInternal.transHandle = *transHandle; memset(&session->transInternal.transDigest, 0, sizeof(TPM_DIGEST)); memcpy(&session->transInternal.transPublic, transPublic, sizeof_TPM_TRANSPORT_PUBLIC((*transPublic))); memcpy(&session->transInternal.transNonceEven, transNonceEven, sizeof(TPM_NONCE)); memcpy(&session->nonceEven, transNonceEven, sizeof(TPM_NONCE)); memcpy(&session->transInternal.authData, trans_auth.authData, sizeof(TPM_AUTHDATA)); *locality = tpmData.stany.flags.localityModifier; memcpy(currentTicks, &tpmData.stany.data.currentTicks, sizeof(TPM_CURRENT_TICKS)); /* perform transport logging */ if (transPublic->transAttributes & TPM_TRANSPORT_LOG) { tpm_sha1_ctx_t sha1; BYTE *ptr, buf[4 + 4 + 4 + sizeof_TPM_CURRENT_TICKS(x) + 20]; UINT32 len; /* log input */ memset(buf, 0, sizeof(buf)); transport_log_in(auth1->digest, buf, &session->transInternal.transDigest); /* compute digest of output parameters and log output */ ptr = buf; len = sizeof(buf); tpm_marshal_UINT32(&ptr, &len, TPM_SUCCESS); tpm_marshal_TPM_COMMAND_CODE(&ptr, &len, TPM_ORD_EstablishTransport); tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len, *locality); tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, currentTicks); tpm_marshal_TPM_NONCE(&ptr, &len, transNonceEven); tpm_sha1_init(&sha1); tpm_sha1_update(&sha1, buf, sizeof(buf)); tpm_sha1_final(&sha1, buf); transport_log_out(buf, &session->transInternal.transDigest); } /* check whether this is a exclusive transport session */ if (transPublic->transAttributes & TPM_TRANSPORT_EXCLUSIVE) { tpmData.stany.flags.transportExclusive = TRUE; tpmData.stany.data.transExclusive = *transHandle; } auth1->continueAuthSession = FALSE; return TPM_SUCCESS; }
TPM_RESULT TPM_LoadContext(TPM_HANDLE entityHandle, BOOL keepHandle, UINT32 contextSize, TPM_CONTEXT_BLOB *contextBlob, TPM_HANDLE *handle) { TPM_CONTEXT_SENSITIVE context; BYTE *context_buf; TPM_SESSION_DATA *session; TPM_DAA_SESSION_DATA *sessionDAA; TPM_KEY_DATA *key; TPM_DIGEST digest; int i = 0; info("TPM_LoadContext()"); if (decrypt_context(contextBlob->additionalData, contextBlob->additionalSize, contextBlob->sensitiveData, contextBlob->sensitiveSize, &context, &context_buf)) return TPM_DECRYPT_ERROR; /* validate structure */ if (compute_context_digest(contextBlob, &digest) || memcmp(&digest, &contextBlob->integrityDigest, sizeof(TPM_DIGEST))) { tpm_free(context_buf); return TPM_BADCONTEXT; } if (contextBlob->resourceType == TPM_RT_KEY) { /* check contextNonce */ if (context.internalData.key.parentPCRStatus || (context.internalData.key.keyFlags & TPM_KEY_FLAG_VOLATILE)) { if (memcmp(&context.contextNonce, &tpmData.stclear.data.contextNonceKey, sizeof(TPM_NONCE)) != 0) { tpm_free(context_buf); return TPM_BADCONTEXT; } } /* check handle */ key = tpm_get_key_slot(entityHandle); if (key == NULL || !key->payload) { if (keepHandle) { tpm_free(context_buf); return TPM_BAD_HANDLE; } *handle = tpm_get_free_key(); if (*handle == TPM_INVALID_HANDLE) { tpm_free(context_buf); return TPM_RESOURCES; } key = &tpmData.permanent.data.keys[HANDLE_TO_INDEX(*handle)]; } else { *handle = entityHandle; } /* reload resource */ memcpy(key, &context.internalData.key, sizeof(TPM_KEY_DATA)); tpm_rsa_copy_key(&key->key, &context.internalData.key.key); } else if (contextBlob->resourceType == TPM_RT_DAA_TPM) { /* check contextNonce */ if (memcmp(&context.contextNonce, &tpmData.stany.data.contextNonceSession, sizeof(TPM_NONCE)) != 0) { tpm_free(context_buf); return TPM_BADCONTEXT; } /* check context list */ for (i = 0; i < TPM_MAX_SESSION_LIST; i++) if (tpmData.stany.data.contextList[i] == contextBlob->contextCount) break; if (i >= TPM_MAX_SESSION_LIST) { tpm_free(context_buf); return TPM_BADCONTEXT; } tpmData.stany.data.contextList[i] = 0; /* check handle */ info("entityHandle = %08x, keepHandle = %d", entityHandle, keepHandle); sessionDAA = tpm_get_daa_slot(entityHandle); if (sessionDAA == NULL) { if (keepHandle) { tpm_free(context_buf); return TPM_BAD_HANDLE; } *handle = tpm_get_free_daa_session(); if (*handle == TPM_INVALID_HANDLE) { tpm_free(context_buf); return TPM_RESOURCES; } sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)]; } else if (sessionDAA->type != TPM_ST_INVALID) { if (keepHandle) { tpm_free(context_buf); return TPM_BAD_HANDLE; } *handle = tpm_get_free_daa_session(); if (*handle == TPM_INVALID_HANDLE) { tpm_free(context_buf); return TPM_RESOURCES; } sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)]; } else { if (HANDLE_TO_RT(entityHandle) != TPM_RT_DAA_TPM) { if (keepHandle) { tpm_free(context_buf); return TPM_BAD_HANDLE; } *handle = tpm_get_free_daa_session(); if (*handle == TPM_INVALID_HANDLE) { tpm_free(context_buf); return TPM_RESOURCES; } sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)]; } else *handle = entityHandle; } /* reload resource */ tpmData.stany.data.currentDAA = *handle; info("stany.data.currentDAA := %.8x", *handle); memset(sessionDAA, 0, sizeof(TPM_DAA_SESSION_DATA)); memcpy(sessionDAA, &context.internalData.sessionDAA, context.internalSize); } else { /* check contextNonce */ if (memcmp(&context.contextNonce, &tpmData.stany.data.contextNonceSession, sizeof(TPM_NONCE)) != 0) { tpm_free(context_buf); return TPM_BADCONTEXT; } if (context.internalData.session.type == TPM_ST_OSAP && tpm_get_key(context.internalData.session.handle) == NULL) { tpm_free(context_buf); return TPM_RESOURCEMISSING; } /* check context list */ for (i = 0; i < TPM_MAX_SESSION_LIST; i++) if (tpmData.stany.data.contextList[i] == contextBlob->contextCount) break; if (i >= TPM_MAX_SESSION_LIST) { tpm_free(context_buf); return TPM_BADCONTEXT; } tpmData.stany.data.contextList[i] = 0; /* check handle */ session = tpm_get_session_slot(entityHandle); if (session == NULL || session->type != TPM_ST_INVALID) { if (keepHandle) { tpm_free(context_buf); return TPM_BAD_HANDLE; } *handle = tpm_get_free_session(context.internalData.session.type); if (*handle == TPM_INVALID_HANDLE) { tpm_free(context_buf); return TPM_RESOURCES; } session = &tpmData.stany.data.sessions[HANDLE_TO_INDEX(*handle)]; } else { *handle = entityHandle; } /* reload resource */ memcpy(session, &context.internalData.session, sizeof(TPM_SESSION_DATA)); } tpm_free(context_buf); return TPM_SUCCESS; }
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_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) {