drivers/wifi: Remove unnecessary data structure copy
[coreboot2.git] / src / security / tpm / tss / tcg-2.0 / tss.c
blob282845e44c18174ab86473529820244dde9f631e
1 /* SPDX-License-Identifier: BSD-3-Clause */
3 #include <console/console.h>
4 #include <endian.h>
5 #include <string.h>
6 #include <vb2_api.h>
7 #include <security/tpm/tis.h>
8 #include <security/tpm/tss.h>
10 #include "tss_structures.h"
11 #include "tss_marshaling.h"
14 * This file provides interface between firmware and TPM2 device. The TPM1.2
15 * API was copied as is and relevant functions modified to comply with the
16 * TPM2 specification.
19 void *tlcl2_process_command(TPM_CC command, void *command_body)
21 struct obuf ob;
22 struct ibuf ib;
23 size_t out_size;
24 size_t in_size;
25 const uint8_t *sendb;
26 /* Command/response buffer. */
27 static uint8_t cr_buffer[TPM_BUFFER_SIZE];
29 if (tlcl_tis_sendrecv == NULL) {
30 printk(BIOS_ERR, "Attempted use of uninitialized TSS 2.0 stack\n");
31 return NULL;
34 obuf_init(&ob, cr_buffer, sizeof(cr_buffer));
36 if (tpm_marshal_command(command, command_body, &ob) < 0) {
37 printk(BIOS_ERR, "command %#x\n", command);
38 return NULL;
41 sendb = obuf_contents(&ob, &out_size);
43 in_size = sizeof(cr_buffer);
44 if (tlcl_tis_sendrecv(sendb, out_size, cr_buffer, &in_size)) {
45 printk(BIOS_ERR, "tpm transaction failed\n");
46 return NULL;
49 ibuf_init(&ib, cr_buffer, in_size);
51 return tpm_unmarshal_response(command, &ib);
54 static tpm_result_t tlcl2_send_startup(TPM_SU type)
56 struct tpm2_startup startup;
57 struct tpm2_response *response;
59 startup.startup_type = type;
60 response = tlcl2_process_command(TPM2_Startup, &startup);
62 /* IO error, tpm2_response pointer is empty. */
63 if (!response) {
64 printk(BIOS_ERR, "%s: TPM communication error\n", __func__);
65 return TPM_IOERROR;
68 printk(BIOS_INFO, "%s: Startup return code is %#x\n",
69 __func__, response->hdr.tpm_code);
71 switch (response->hdr.tpm_code) {
72 case TPM_RC_INITIALIZE:
73 /* TPM already initialized. */
74 return TPM_INVALID_POSTINIT;
75 case TPM2_RC_SUCCESS:
76 return TPM_SUCCESS;
79 /* Collapse any other errors into TPM_IOERROR. */
80 return TPM_IOERROR;
83 tpm_result_t tlcl2_resume(void)
85 return tlcl2_send_startup(TPM_SU_STATE);
88 static tpm_result_t tlcl2_send_shutdown(TPM_SU type)
90 struct tpm2_shutdown shutdown;
91 struct tpm2_response *response;
93 shutdown.shutdown_type = type;
94 response = tlcl2_process_command(TPM2_Shutdown, &shutdown);
96 /* IO error, tpm2_response pointer is empty. */
97 if (!response) {
98 printk(BIOS_ERR, "%s: TPM communication error\n", __func__);
99 return TPM_IOERROR;
102 printk(BIOS_INFO, "%s: Shutdown return code is %#x\n",
103 __func__, response->hdr.tpm_code);
105 if (response->hdr.tpm_code == TPM2_RC_SUCCESS)
106 return TPM_SUCCESS;
108 /* Collapse any other errors into TPM_IOERROR. */
109 return TPM_IOERROR;
112 tpm_result_t tlcl2_save_state(void)
114 return tlcl2_send_shutdown(TPM_SU_STATE);
117 tpm_result_t tlcl2_assert_physical_presence(void)
120 * Nothing to do on TPM2 for this, use platform hierarchy availability
121 * instead.
123 return TPM_SUCCESS;
126 static TPM_ALG_ID tpmalg_from_vb2_hash(enum vb2_hash_algorithm hash_type)
128 switch (hash_type) {
129 case VB2_HASH_SHA1:
130 return TPM_ALG_SHA1;
131 case VB2_HASH_SHA256:
132 return TPM_ALG_SHA256;
133 case VB2_HASH_SHA384:
134 return TPM_ALG_SHA384;
135 case VB2_HASH_SHA512:
136 return TPM_ALG_SHA512;
138 default:
139 return TPM_ALG_ERROR;
144 * The caller will provide the digest in a 32 byte buffer, let's consider it a
145 * sha256 digest.
147 tpm_result_t tlcl2_extend(int pcr_num, const uint8_t *digest_data,
148 enum vb2_hash_algorithm digest_type)
150 struct tpm2_pcr_extend_cmd pcr_ext_cmd;
151 struct tpm2_response *response;
152 TPM_ALG_ID alg;
154 alg = tpmalg_from_vb2_hash(digest_type);
155 if (alg == TPM_ALG_ERROR)
156 return TPM_CB_HASH_ERROR;
158 pcr_ext_cmd.pcrHandle = HR_PCR + pcr_num;
159 pcr_ext_cmd.digests.count = 1;
160 pcr_ext_cmd.digests.digests[0].hashAlg = alg;
161 /* Always copying to sha512 as it's the largest one */
162 memcpy(pcr_ext_cmd.digests.digests[0].digest.sha512, digest_data,
163 vb2_digest_size(digest_type));
165 response = tlcl2_process_command(TPM2_PCR_Extend, &pcr_ext_cmd);
167 printk(BIOS_INFO, "%s: response is %#x\n",
168 __func__, response ? response->hdr.tpm_code : -1);
169 if (!response || response->hdr.tpm_code)
170 return TPM_IOERROR;
172 return TPM_SUCCESS;
175 tpm_result_t tlcl2_finalize_physical_presence(void)
177 /* Nothing needs to be done with tpm2. */
178 printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
179 return TPM_SUCCESS;
182 tpm_result_t tlcl2_force_clear(void)
184 struct tpm2_response *response;
186 response = tlcl2_process_command(TPM2_Clear, NULL);
187 printk(BIOS_INFO, "%s: response is %#x\n",
188 __func__, response ? response->hdr.tpm_code : -1);
190 if (!response || response->hdr.tpm_code)
191 return TPM_IOERROR;
193 return TPM_SUCCESS;
196 tpm_result_t tlcl2_clear_control(bool disable)
198 struct tpm2_response *response;
199 struct tpm2_clear_control_cmd cc = {
200 .disable = 0,
203 response = tlcl2_process_command(TPM2_ClearControl, &cc);
204 printk(BIOS_INFO, "%s: response is %#x\n",
205 __func__, response ? response->hdr.tpm_code : -1);
207 if (!response || response->hdr.tpm_code)
208 return TPM_IOERROR;
210 return TPM_SUCCESS;
213 tpm_result_t tlcl2_physical_presence_cmd_enable(void)
215 printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
216 return TPM_SUCCESS;
219 tpm_result_t tlcl2_read(uint32_t index, void *data, uint32_t length)
221 struct tpm2_nv_read_cmd nv_readc;
222 struct tpm2_response *response;
224 memset(&nv_readc, 0, sizeof(nv_readc));
226 nv_readc.nvIndex = HR_NV_INDEX + index;
227 nv_readc.size = length;
229 response = tlcl2_process_command(TPM2_NV_Read, &nv_readc);
231 /* Need to map tpm error codes into internal values. */
232 if (!response)
233 return TPM_CB_READ_FAILURE;
235 printk(BIOS_INFO, "%s:%d index %#x return code %#x\n",
236 __FILE__, __LINE__, index, response->hdr.tpm_code);
237 switch (response->hdr.tpm_code) {
238 case 0:
239 break;
241 /* Uninitialized, returned if the space hasn't been written. */
242 case TPM_RC_NV_UNINITIALIZED:
244 * Bad index, cr50 specific value, returned if the space
245 * hasn't been defined.
247 case TPM_RC_CR50_NV_UNDEFINED:
248 return TPM_BADINDEX;
250 case TPM_RC_NV_RANGE:
251 return TPM_CB_RANGE;
253 default:
254 return TPM_CB_READ_FAILURE;
257 if (length > response->nvr.buffer.t.size)
258 return TPM_CB_RESPONSE_TOO_LARGE;
260 if (length < response->nvr.buffer.t.size)
261 return TPM_CB_READ_EMPTY;
263 memcpy(data, response->nvr.buffer.t.buffer, length);
265 return TPM_SUCCESS;
268 tpm_result_t tlcl2_self_test_full(void)
270 struct tpm2_self_test st;
271 struct tpm2_response *response;
273 st.yes_no = 1;
275 response = tlcl2_process_command(TPM2_SelfTest, &st);
276 printk(BIOS_INFO, "%s: response is %#x\n",
277 __func__, response ? response->hdr.tpm_code : -1);
278 return TPM_SUCCESS;
281 tpm_result_t tlcl2_lock_nv_write(uint32_t index)
283 struct tpm2_response *response;
284 /* TPM Will reject attempts to write at non-defined index. */
285 struct tpm2_nv_write_lock_cmd nv_wl = {
286 .nvIndex = HR_NV_INDEX + index,
289 response = tlcl2_process_command(TPM2_NV_WriteLock, &nv_wl);
291 printk(BIOS_INFO, "%s: response is %#x\n",
292 __func__, response ? response->hdr.tpm_code : -1);
294 if (!response || response->hdr.tpm_code)
295 return TPM_IOERROR;
297 return TPM_SUCCESS;
300 tpm_result_t tlcl2_startup(void)
302 return tlcl2_send_startup(TPM_SU_CLEAR);
305 tpm_result_t tlcl2_write(uint32_t index, const void *data, uint32_t length)
307 struct tpm2_nv_write_cmd nv_writec;
308 struct tpm2_response *response;
310 memset(&nv_writec, 0, sizeof(nv_writec));
312 nv_writec.nvIndex = HR_NV_INDEX + index;
313 nv_writec.data.t.size = length;
314 nv_writec.data.t.buffer = data;
316 response = tlcl2_process_command(TPM2_NV_Write, &nv_writec);
318 printk(BIOS_INFO, "%s: response is %#x\n",
319 __func__, response ? response->hdr.tpm_code : -1);
321 /* Need to map tpm error codes into internal values. */
322 if (!response || response->hdr.tpm_code)
323 return TPM_CB_WRITE_FAILURE;
325 return TPM_SUCCESS;
328 tpm_result_t tlcl2_set_bits(uint32_t index, uint64_t bits)
330 struct tpm2_nv_setbits_cmd nvsb_cmd;
331 struct tpm2_response *response;
333 /* Prepare the command structure */
334 memset(&nvsb_cmd, 0, sizeof(nvsb_cmd));
336 nvsb_cmd.nvIndex = HR_NV_INDEX + index;
337 nvsb_cmd.bits = bits;
339 response = tlcl2_process_command(TPM2_NV_SetBits, &nvsb_cmd);
341 printk(BIOS_INFO, "%s: response is %#x\n",
342 __func__, response ? response->hdr.tpm_code : -1);
344 /* Need to map tpm error codes into internal values. */
345 if (!response || response->hdr.tpm_code)
346 return TPM_CB_WRITE_FAILURE;
348 return TPM_SUCCESS;
351 tpm_result_t tlcl2_define_space(uint32_t space_index, size_t space_size,
352 const TPMA_NV nv_attributes,
353 const uint8_t *nv_policy, size_t nv_policy_size)
355 struct tpm2_nv_define_space_cmd nvds_cmd;
356 struct tpm2_response *response;
358 /* Prepare the define space command structure. */
359 memset(&nvds_cmd, 0, sizeof(nvds_cmd));
361 nvds_cmd.publicInfo.dataSize = space_size;
362 nvds_cmd.publicInfo.nvIndex = HR_NV_INDEX + space_index;
363 nvds_cmd.publicInfo.nameAlg = TPM_ALG_SHA256;
364 nvds_cmd.publicInfo.attributes = nv_attributes;
367 * Use policy digest based on default pcr0 value. This makes
368 * sure that the space can not be deleted as soon as PCR0
369 * value has been extended from default.
371 if (nv_policy && nv_policy_size) {
372 nvds_cmd.publicInfo.authPolicy.t.buffer = nv_policy;
373 nvds_cmd.publicInfo.authPolicy.t.size = nv_policy_size;
376 response = tlcl2_process_command(TPM2_NV_DefineSpace, &nvds_cmd);
377 printk(BIOS_INFO, "%s: response is %#x\n", __func__,
378 response ? response->hdr.tpm_code : -1);
380 if (!response)
381 return TPM_CB_NO_DEVICE;
383 /* Map TPM2 return codes into common vboot representation. */
384 switch (response->hdr.tpm_code) {
385 case TPM2_RC_SUCCESS:
386 return TPM_SUCCESS;
387 case TPM2_RC_NV_DEFINED:
388 return TPM_CB_NV_DEFINED;
389 default:
390 return TPM_CB_INTERNAL_INCONSISTENCY;
394 uint16_t tlcl2_get_hash_size_from_algo(TPMI_ALG_HASH hash_algo)
396 uint16_t value;
398 switch (hash_algo) {
399 case TPM_ALG_ERROR:
400 value = 1;
401 break;
402 case TPM_ALG_SHA1:
403 value = SHA1_DIGEST_SIZE;
404 break;
405 case TPM_ALG_SHA256:
406 value = SHA256_DIGEST_SIZE;
407 break;
408 case TPM_ALG_SHA384:
409 value = SHA384_DIGEST_SIZE;
410 break;
411 case TPM_ALG_SHA512:
412 value = SHA512_DIGEST_SIZE;
413 break;
414 case TPM_ALG_SM3_256:
415 value = SM3_256_DIGEST_SIZE;
416 break;
417 default:
418 printk(BIOS_SPEW, "%s: unknown hash algorithm %d\n", __func__,
419 hash_algo);
420 value = 0;
423 return value;
426 tpm_result_t tlcl2_disable_platform_hierarchy(void)
428 struct tpm2_response *response;
429 struct tpm2_hierarchy_control_cmd hc = {
430 .enable = TPM_RH_PLATFORM,
431 .state = 0,
434 response = tlcl2_process_command(TPM2_Hierarchy_Control, &hc);
436 if (!response || response->hdr.tpm_code)
437 return TPM_CB_INTERNAL_INCONSISTENCY;
439 return TPM_SUCCESS;
442 tpm_result_t tlcl2_get_capability(TPM_CAP capability, uint32_t property,
443 uint32_t property_count,
444 TPMS_CAPABILITY_DATA *capability_data)
446 struct tpm2_get_capability cmd;
447 struct tpm2_response *response;
449 cmd.capability = capability;
450 cmd.property = property;
451 cmd.propertyCount = property_count;
453 if (property_count > 1) {
454 printk(BIOS_ERR, "%s: property_count more than one not "
455 "supported yet\n", __func__);
456 return TPM_IOERROR;
459 response = tlcl2_process_command(TPM2_GetCapability, &cmd);
461 if (!response) {
462 printk(BIOS_ERR, "%s: Command Failed\n", __func__);
463 return TPM_IOERROR;
466 memcpy(capability_data, &response->gc.cd, sizeof(TPMS_CAPABILITY_DATA));
467 return TPM_SUCCESS;