123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525 |
- /*
- * Copyright 2016 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Some TPM constants and type definitions for standalone compilation for use
- * in the firmware
- */
- #include "2sysincludes.h"
- #include "2common.h"
- #include "rollback_index.h"
- #include "tpm2_marshaling.h"
- #include "utility.h"
- #include "tlcl.h"
- static struct tpm2_response *tpm_process_command(TPM_CC command,
- void *command_body)
- {
- /* Command/response buffer. */
- static uint8_t cr_buffer[TPM_BUFFER_SIZE];
- uint32_t out_size, in_size;
- struct tpm2_response *response;
- out_size = tpm_marshal_command(command, command_body,
- cr_buffer, sizeof(cr_buffer));
- if (out_size < 0) {
- VB2_DEBUG("command %#x, cr size %d\n", command, out_size);
- return NULL;
- }
- in_size = sizeof(cr_buffer);
- if (VbExTpmSendReceive(cr_buffer, out_size,
- cr_buffer, &in_size) != TPM_SUCCESS) {
- VB2_DEBUG("tpm transaction failed for %#x\n", command);
- return NULL;
- }
- response = tpm_unmarshal_response(command, cr_buffer, in_size);
- VB2_DEBUG("command %#x, return code %#x\n", command,
- response ? response->hdr.tpm_code : -1);
- return response;
- }
- static uint32_t tlcl_read_ph_disabled(void)
- {
- uint32_t rv;
- TPM_STCLEAR_FLAGS flags;
- rv = TlclGetSTClearFlags(&flags);
- if (rv != TPM_SUCCESS)
- return rv;
- tpm_set_ph_disabled(!flags.phEnable);
- return TPM_SUCCESS;
- }
- uint32_t TlclLibInit(void)
- {
- uint32_t rv;
- rv = VbExTpmInit();
- if (rv != TPM_SUCCESS)
- return rv;
- rv = tlcl_read_ph_disabled();
- if (rv != TPM_SUCCESS) {
- TlclLibClose();
- return rv;
- }
- return TPM_SUCCESS;
- }
- uint32_t TlclLibClose(void)
- {
- return VbExTpmClose();
- }
- uint32_t TlclSendReceive(const uint8_t *request, uint8_t *response,
- int max_length)
- {
- uint32_t rv, resp_size;
- resp_size = max_length;
- rv = VbExTpmSendReceive(request, tpm_get_packet_size(request),
- response, &resp_size);
- return rv ? rv : tpm_get_packet_response_code(response);
- }
- int TlclPacketSize(const uint8_t *packet)
- {
- return tpm_get_packet_size(packet);
- }
- uint32_t TlclStartup(void)
- {
- struct tpm2_response *response;
- struct tpm2_startup_cmd startup;
- startup.startup_type = TPM_SU_CLEAR;
- response = tpm_process_command(TPM2_Startup, &startup);
- if (!response || response->hdr.tpm_code)
- return TPM_E_IOERROR;
- return TPM_SUCCESS;
- }
- uint32_t TlclSaveState(void)
- {
- struct tpm2_response *response;
- struct tpm2_shutdown_cmd shutdown;
- shutdown.shutdown_type = TPM_SU_STATE;
- response = tpm_process_command(TPM2_Shutdown, &shutdown);
- if (!response || response->hdr.tpm_code)
- return TPM_E_IOERROR;
- return TPM_SUCCESS;
- }
- uint32_t TlclResume(void)
- {
- struct tpm2_response *response;
- struct tpm2_startup_cmd startup;
- startup.startup_type = TPM_SU_STATE;
- response = tpm_process_command(TPM2_Startup, &startup);
- if (!response || response->hdr.tpm_code)
- return TPM_E_IOERROR;
- return TPM_SUCCESS;
- }
- uint32_t TlclSelfTestFull(void)
- {
- struct tpm2_response *response;
- struct tpm2_self_test_cmd self_test;
- self_test.full_test = 1;
- response = tpm_process_command(TPM2_SelfTest, &self_test);
- if (!response || response->hdr.tpm_code)
- return TPM_E_IOERROR;
- return TPM_SUCCESS;
- }
- uint32_t TlclContinueSelfTest(void)
- {
- struct tpm2_response *response;
- struct tpm2_self_test_cmd self_test;
- self_test.full_test = 0;
- response = tpm_process_command(TPM2_SelfTest, &self_test);
- if (!response || response->hdr.tpm_code)
- return TPM_E_IOERROR;
- return TPM_SUCCESS;
- }
- uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size)
- {
- struct tpm2_response *response;
- struct tpm2_nv_define_space_cmd define_space;
- /* For backwards-compatibility, if no READ or WRITE permissions are set,
- * assume readable/writeable with empty auth value.
- */
- if (!(perm & TPMA_NV_MASK_WRITE))
- perm |= TPMA_NV_AUTHWRITE;
- if (!(perm & TPMA_NV_MASK_READ))
- perm |= TPMA_NV_AUTHREAD;
- memset(&define_space, 0, sizeof(define_space));
- define_space.publicInfo.nvIndex = HR_NV_INDEX + index;
- define_space.publicInfo.dataSize = size;
- define_space.publicInfo.attributes = perm;
- define_space.publicInfo.nameAlg = TPM_ALG_SHA256;
- response = tpm_process_command(TPM2_NV_DefineSpace, &define_space);
- if (!response || response->hdr.tpm_code)
- return TPM_E_IOERROR;
- return TPM_SUCCESS;
- }
- /**
- * Issue a ForceClear. The TPM error code is returned.
- */
- uint32_t TlclForceClear(void)
- {
- struct tpm2_response *response;
- response = tpm_process_command(TPM2_Clear, NULL);
- if (!response || response->hdr.tpm_code)
- return TPM_E_IOERROR;
- return TPM_SUCCESS;
- }
- uint32_t TlclSetDeactivated(uint8_t flag)
- {
- VB2_DEBUG("NOT YET IMPLEMENTED\n");
- return TPM_SUCCESS;
- }
- uint32_t TlclSetEnable(void)
- {
- VB2_DEBUG("NOT YET IMPLEMENTED\n");
- return TPM_SUCCESS;
- }
- uint32_t TlclGetFlags(uint8_t* disable,
- uint8_t* deactivated,
- uint8_t *nvlocked)
- {
- /* For TPM2 the flags are always the same */
- if (disable)
- *disable = 0;
- if (deactivated)
- *deactivated = 0;
- if (nvlocked)
- *nvlocked = 1;
- return TPM_SUCCESS;
- }
- int TlclIsOwned(void)
- {
- VB2_DEBUG("NOT YET IMPLEMENTED\n");
- return 0;
- }
- uint32_t TlclExtend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest)
- {
- VB2_DEBUG("NOT YET IMPLEMENTED\n");
- return TPM_SUCCESS;
- }
- static uint32_t tlcl_nv_read_public(uint32_t index,
- struct nv_read_public_response **presp)
- {
- struct tpm2_response *response;
- struct tpm2_nv_read_public_cmd read_pub;
- memset(&read_pub, 0, sizeof(read_pub));
- read_pub.nvIndex = HR_NV_INDEX + index;
- response = tpm_process_command(TPM2_NV_ReadPublic, &read_pub);
- if (!response || response->hdr.tpm_code)
- return TPM_E_IOERROR;
- *presp = &response->nv_read_public;
- return TPM_SUCCESS;
- }
- /**
- * Get the permission bits for the NVRAM space with |index|.
- */
- uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions)
- {
- uint32_t rv;
- struct nv_read_public_response *resp;
- rv = tlcl_nv_read_public(index, &resp);
- if (rv != TPM_SUCCESS)
- return rv;
- *permissions = resp->nvPublic.attributes;
- return TPM_SUCCESS;
- }
- static uint32_t tlcl_get_capability(TPM_CAP cap, TPM_PT property,
- struct get_capability_response **presp)
- {
- struct tpm2_response *response;
- struct tpm2_get_capability_cmd getcap;
- getcap.capability = cap;
- getcap.property = property;
- getcap.property_count = 1;
- response = tpm_process_command(TPM2_GetCapability, &getcap);
- if (!response || response->hdr.tpm_code)
- return TPM_E_IOERROR;
- *presp = &response->cap;
- return TPM_SUCCESS;
- }
- static uint32_t tlcl_get_tpm_property(TPM_PT property, uint32_t *pvalue)
- {
- uint32_t rv;
- struct get_capability_response *resp;
- TPML_TAGGED_TPM_PROPERTY *tpm_prop;
- rv = tlcl_get_capability(TPM_CAP_TPM_PROPERTIES, property, &resp);
- if (rv != TPM_SUCCESS)
- return rv;
- if (resp->capability_data.capability != TPM_CAP_TPM_PROPERTIES)
- return TPM_E_IOERROR;
- tpm_prop = &resp->capability_data.data.tpm_properties;
- if ((tpm_prop->count != 1) ||
- (tpm_prop->tpm_property[0].property != property))
- return TPM_E_IOERROR;
- *pvalue = tpm_prop->tpm_property[0].value;
- return TPM_SUCCESS;
- }
- uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags)
- {
- return tlcl_get_tpm_property(TPM_PT_PERMANENT,
- (uint32_t *)pflags);
- }
- uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS *pflags)
- {
- return tlcl_get_tpm_property(TPM_PT_STARTUP_CLEAR,
- (uint32_t *)pflags);
- }
- uint32_t TlclGetOwnership(uint8_t *owned)
- {
- uint32_t rv;
- TPM_PERMANENT_FLAGS flags;
- *owned = 0;
- rv = TlclGetPermanentFlags(&flags);
- if (rv != TPM_SUCCESS)
- return rv;
- *owned = flags.ownerAuthSet;
- return TPM_SUCCESS;
- }
- static uint32_t tlcl_lock_nv_write(uint32_t index)
- {
- struct tpm2_response *response;
- struct tpm2_nv_write_lock_cmd nv_wl;
- nv_wl.nvIndex = HR_NV_INDEX + index;
- response = tpm_process_command(TPM2_NV_WriteLock, &nv_wl);
- if (!response || response->hdr.tpm_code)
- return TPM_E_INTERNAL_INCONSISTENCY;
- return TPM_SUCCESS;
- }
- static uint32_t tlcl_disable_platform_hierarchy(void)
- {
- struct tpm2_response *response;
- struct tpm2_hierarchy_control_cmd hc;
- hc.enable = TPM_RH_PLATFORM;
- hc.state = 0;
- response = tpm_process_command(TPM2_Hierarchy_Control, &hc);
- if (!response || response->hdr.tpm_code)
- return TPM_E_INTERNAL_INCONSISTENCY;
- tpm_set_ph_disabled(1);
- return TPM_SUCCESS;
- }
- /**
- * The name of the function was kept to maintain the existing TPM API, but
- * TPM2.0 does not use the global lock to protect the FW rollback counter.
- * Instead it calls WriteLock for the FW NVRAM index to prevent future
- * writes to it.
- *
- * It first checks if the platform hierarchy is already disabled, and does
- * nothing, if so. Otherwise, WriteLock for the index obviously fails.
- */
- uint32_t TlclSetGlobalLock(void)
- {
- if (tpm_is_ph_disabled())
- return TPM_SUCCESS;
- else
- return tlcl_lock_nv_write(FIRMWARE_NV_INDEX);
- }
- /**
- * Turn off physical presence and locks it off until next reboot. The TPM
- * error code is returned.
- *
- * The name of the function was kept to maintain the existing TPM API, but
- * TPM2.0 does not have to use the Physical Presence concept. Instead it just
- * removes platform authorization - this makes sure that firmware and kernel
- * rollback counter spaces can not be modified.
- *
- * It also explicitly locks the kernel rollback counter space (the FW rollback
- * counter space was locked before RW firmware started.)
- */
- uint32_t TlclLockPhysicalPresence(void)
- {
- if (tpm_is_ph_disabled())
- return TPM_SUCCESS;
- return tlcl_disable_platform_hierarchy();
- }
- uint32_t TlclRead(uint32_t index, void* data, uint32_t length)
- {
- struct tpm2_nv_read_cmd nv_readc;
- struct tpm2_response *response;
- memset(&nv_readc, 0, sizeof(nv_readc));
- nv_readc.nvIndex = HR_NV_INDEX + index;
- nv_readc.size = length;
- response = tpm_process_command(TPM2_NV_Read, &nv_readc);
- /* Need to map tpm error codes into internal values. */
- if (!response)
- return TPM_E_READ_FAILURE;
- switch (response->hdr.tpm_code) {
- case 0:
- break;
- case 0x28b:
- return TPM_E_BADINDEX;
- default:
- return TPM_E_READ_FAILURE;
- }
- if (length > response->nvr.buffer.t.size)
- return TPM_E_RESPONSE_TOO_LARGE;
- if (length < response->nvr.buffer.t.size)
- return TPM_E_READ_EMPTY;
- memcpy(data, response->nvr.buffer.t.buffer, length);
- return TPM_SUCCESS;
- }
- uint32_t TlclWrite(uint32_t index, const void *data, uint32_t length)
- {
- struct tpm2_nv_write_cmd nv_writec;
- struct tpm2_response *response;
- memset(&nv_writec, 0, sizeof(nv_writec));
- nv_writec.nvIndex = HR_NV_INDEX + index;
- nv_writec.data.t.size = length;
- nv_writec.data.t.buffer = data;
- response = tpm_process_command(TPM2_NV_Write, &nv_writec);
- /* Need to map tpm error codes into internal values. */
- if (!response || response->hdr.tpm_code)
- return TPM_E_WRITE_FAILURE;
- return TPM_SUCCESS;
- }
- uint32_t TlclPCRRead(uint32_t index, void *data, uint32_t length)
- {
- VB2_DEBUG("NOT YET IMPLEMENTED\n");
- return TPM_SUCCESS;
- }
- uint32_t TlclWriteLock(uint32_t index)
- {
- struct tpm2_nv_write_lock_cmd nv_writelockc;
- struct tpm2_response *response;
- memset(&nv_writelockc, 0, sizeof(nv_writelockc));
- nv_writelockc.nvIndex = HR_NV_INDEX | index;
- response = tpm_process_command(TPM2_NV_WriteLock, &nv_writelockc);
- /* Need to map tpm error codes into internal values. */
- if (!response || response->hdr.tpm_code)
- return TPM_E_WRITE_FAILURE;
- return TPM_SUCCESS;
- }
- uint32_t TlclReadLock(uint32_t index)
- {
- struct tpm2_nv_read_lock_cmd nv_readlockc;
- struct tpm2_response *response;
- memset(&nv_readlockc, 0, sizeof(nv_readlockc));
- nv_readlockc.nvIndex = HR_NV_INDEX | index;
- response = tpm_process_command(TPM2_NV_ReadLock, &nv_readlockc);
- /* Need to map tpm error codes into internal values. */
- if (!response || response->hdr.tpm_code)
- return TPM_E_READ_FAILURE;
- return TPM_SUCCESS;
- }
- uint32_t TlclGetRandom(uint8_t *data, uint32_t length, uint32_t *size)
- {
- *size = 0;
- VB2_DEBUG("NOT YET IMPLEMENTED\n");
- return TPM_E_IOERROR;
- }
|