2 * Copyright 2016 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
6 * Some TPM constants and type definitions for standalone compilation for use
10 #include "rollback_index.h"
11 #include "tpm2_marshaling.h"
15 static struct tpm2_response *tpm_process_command(TPM_CC command,
18 /* Command/response buffer. */
19 static uint8_t cr_buffer[TPM_BUFFER_SIZE];
20 uint32_t out_size, in_size;
21 struct tpm2_response *response;
23 out_size = tpm_marshal_command(command, command_body,
24 cr_buffer, sizeof(cr_buffer));
26 VBDEBUG(("command %#x, cr size %d\n",
31 in_size = sizeof(cr_buffer);
32 if (VbExTpmSendReceive(cr_buffer, out_size,
33 cr_buffer, &in_size) != TPM_SUCCESS) {
34 VBDEBUG(("tpm transaction failed for %#x\n", command));
38 response = tpm_unmarshal_response(command, cr_buffer, in_size);
40 VBDEBUG(("%s: command %#x, return code %#x\n", __func__, command,
41 response ? response->hdr.tpm_code : -1));
46 static uint32_t tlcl_read_ph_disabled(void)
49 TPM_STCLEAR_FLAGS flags;
51 rv = TlclGetSTClearFlags(&flags);
52 if (rv != TPM_SUCCESS)
55 tpm_set_ph_disabled(!flags.phEnable);
60 uint32_t TlclLibInit(void)
65 if (rv != TPM_SUCCESS)
68 rv = tlcl_read_ph_disabled();
69 if (rv != TPM_SUCCESS) {
77 uint32_t TlclLibClose(void)
79 return VbExTpmClose();
82 uint32_t TlclSendReceive(const uint8_t *request, uint8_t *response,
85 uint32_t rv, resp_size;
87 resp_size = max_length;
88 rv = VbExTpmSendReceive(request, tpm_get_packet_size(request),
89 response, &resp_size);
91 return rv ? rv : tpm_get_packet_response_code(response);
94 int TlclPacketSize(const uint8_t *packet)
96 return tpm_get_packet_size(packet);
99 uint32_t TlclStartup(void)
101 struct tpm2_response *response;
102 struct tpm2_startup_cmd startup;
104 startup.startup_type = TPM_SU_CLEAR;
106 response = tpm_process_command(TPM2_Startup, &startup);
107 if (!response || response->hdr.tpm_code)
108 return TPM_E_IOERROR;
113 uint32_t TlclSaveState(void)
115 struct tpm2_response *response;
116 struct tpm2_shutdown_cmd shutdown;
118 shutdown.shutdown_type = TPM_SU_STATE;
120 response = tpm_process_command(TPM2_Shutdown, &shutdown);
121 if (!response || response->hdr.tpm_code)
122 return TPM_E_IOERROR;
127 uint32_t TlclResume(void)
129 struct tpm2_response *response;
130 struct tpm2_startup_cmd startup;
132 startup.startup_type = TPM_SU_STATE;
134 response = tpm_process_command(TPM2_Startup, &startup);
135 if (!response || response->hdr.tpm_code)
136 return TPM_E_IOERROR;
141 uint32_t TlclSelfTestFull(void)
143 struct tpm2_response *response;
144 struct tpm2_self_test_cmd self_test;
146 self_test.full_test = 1;
148 response = tpm_process_command(TPM2_SelfTest, &self_test);
149 if (!response || response->hdr.tpm_code)
150 return TPM_E_IOERROR;
155 uint32_t TlclContinueSelfTest(void)
157 struct tpm2_response *response;
158 struct tpm2_self_test_cmd self_test;
160 self_test.full_test = 0;
162 response = tpm_process_command(TPM2_SelfTest, &self_test);
163 if (!response || response->hdr.tpm_code)
164 return TPM_E_IOERROR;
169 uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size)
171 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
176 * Issue a ForceClear. The TPM error code is returned.
178 uint32_t TlclForceClear(void)
180 struct tpm2_response *response;
182 response = tpm_process_command(TPM2_Clear, NULL);
183 if (!response || response->hdr.tpm_code)
184 return TPM_E_IOERROR;
189 uint32_t TlclSetDeactivated(uint8_t flag)
191 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
195 uint32_t TlclSetEnable(void)
197 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
201 uint32_t TlclGetFlags(uint8_t* disable,
202 uint8_t* deactivated,
205 /* For TPM2 the flags are always the same */
215 int TlclIsOwned(void)
217 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
221 uint32_t TlclExtend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest)
223 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
228 * Get the permission bits for the NVRAM space with |index|.
230 uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions)
233 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
237 static uint32_t tlcl_get_capability(TPM_CAP cap, TPM_PT property,
238 struct get_capability_response **presp)
240 struct tpm2_response *response;
241 struct tpm2_get_capability_cmd getcap;
243 getcap.capability = cap;
244 getcap.property = property;
245 getcap.property_count = 1;
247 response = tpm_process_command(TPM2_GetCapability, &getcap);
248 if (!response || response->hdr.tpm_code)
249 return TPM_E_IOERROR;
250 *presp = &response->cap;
255 static uint32_t tlcl_get_tpm_property(TPM_PT property, uint32_t *pvalue)
258 struct get_capability_response *resp;
259 TPML_TAGGED_TPM_PROPERTY *tpm_prop;
261 rv = tlcl_get_capability(TPM_CAP_TPM_PROPERTIES, property, &resp);
262 if (rv != TPM_SUCCESS)
265 if (resp->capability_data.capability != TPM_CAP_TPM_PROPERTIES)
266 return TPM_E_IOERROR;
268 tpm_prop = &resp->capability_data.data.tpm_properties;
270 if ((tpm_prop->count != 1) ||
271 (tpm_prop->tpm_property[0].property != property))
272 return TPM_E_IOERROR;
274 *pvalue = tpm_prop->tpm_property[0].value;
278 uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags)
280 return tlcl_get_tpm_property(TPM_PT_PERMANENT,
284 uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS *pflags)
286 return tlcl_get_tpm_property(TPM_PT_STARTUP_CLEAR,
290 uint32_t TlclGetOwnership(uint8_t *owned)
293 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
297 static uint32_t tlcl_lock_nv_write(uint32_t index)
299 struct tpm2_response *response;
300 struct tpm2_nv_write_lock_cmd nv_wl;
302 nv_wl.nvIndex = HR_NV_INDEX + index;
303 response = tpm_process_command(TPM2_NV_WriteLock, &nv_wl);
305 if (!response || response->hdr.tpm_code)
306 return TPM_E_INTERNAL_INCONSISTENCY;
311 static uint32_t tlcl_disable_platform_hierarchy(void)
313 struct tpm2_response *response;
314 struct tpm2_hierarchy_control_cmd hc;
316 hc.enable = TPM_RH_PLATFORM;
319 response = tpm_process_command(TPM2_Hierarchy_Control, &hc);
321 if (!response || response->hdr.tpm_code)
322 return TPM_E_INTERNAL_INCONSISTENCY;
324 tpm_set_ph_disabled(1);
329 * The name of the function was kept to maintain the existing TPM API, but
330 * TPM2.0 does not use the global lock to protect the FW rollback counter.
331 * Instead it calls WriteLock for the FW NVRAM index to prevent future
334 * It first checks if the platform hierarchy is already disabled, and does
335 * nothing, if so. Otherwise, WriteLock for the index obviously fails.
337 uint32_t TlclSetGlobalLock(void)
339 if (tpm_is_ph_disabled())
342 return tlcl_lock_nv_write(FIRMWARE_NV_INDEX);
346 * Turn off physical presence and locks it off until next reboot. The TPM
347 * error code is returned.
349 * The name of the function was kept to maintain the existing TPM API, but
350 * TPM2.0 does not have to use the Physical Presence concept. Instead it just
351 * removes platform authorization - this makes sure that firmware and kernel
352 * rollback counter spaces can not be modified.
354 * It also explicitly locks the kernel rollback counter space (the FW rollback
355 * counter space was locked before RW firmware started.)
357 uint32_t TlclLockPhysicalPresence(void)
361 if (tpm_is_ph_disabled())
364 rv = tlcl_lock_nv_write(KERNEL_NV_INDEX);
365 if (rv == TPM_SUCCESS)
366 rv = tlcl_disable_platform_hierarchy();
371 uint32_t TlclRead(uint32_t index, void* data, uint32_t length)
373 struct tpm2_nv_read_cmd nv_readc;
374 struct tpm2_response *response;
376 Memset(&nv_readc, 0, sizeof(nv_readc));
378 nv_readc.nvIndex = HR_NV_INDEX + index;
379 nv_readc.size = length;
381 response = tpm_process_command(TPM2_NV_Read, &nv_readc);
383 /* Need to map tpm error codes into internal values. */
385 return TPM_E_READ_FAILURE;
387 switch (response->hdr.tpm_code) {
392 return TPM_E_BADINDEX;
395 return TPM_E_READ_FAILURE;
398 if (length > response->nvr.buffer.t.size)
399 return TPM_E_RESPONSE_TOO_LARGE;
401 if (length < response->nvr.buffer.t.size)
402 return TPM_E_READ_EMPTY;
404 Memcpy(data, response->nvr.buffer.t.buffer, length);
409 uint32_t TlclWrite(uint32_t index, const void *data, uint32_t length)
411 struct tpm2_nv_write_cmd nv_writec;
412 struct tpm2_response *response;
414 Memset(&nv_writec, 0, sizeof(nv_writec));
416 nv_writec.nvIndex = HR_NV_INDEX + index;
417 nv_writec.data.t.size = length;
418 nv_writec.data.t.buffer = data;
420 response = tpm_process_command(TPM2_NV_Write, &nv_writec);
422 /* Need to map tpm error codes into internal values. */
424 return TPM_E_WRITE_FAILURE;
429 uint32_t TlclPCRRead(uint32_t index, void *data, uint32_t length)
431 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
435 uint32_t TlclWriteLock(uint32_t index)
437 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
441 uint32_t TlclReadLock(uint32_t index)
443 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
447 uint32_t TlclGetRandom(uint8_t *data, uint32_t length, uint32_t *size)
450 VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
451 return TPM_E_IOERROR;