xref: /openbmc/u-boot/lib/tpm_api.c (revision edd88824c7d002ce936c1dfd32acaac1a8e4fb75)
1d7869cecSEddie James // SPDX-License-Identifier: GPL-2.0+
2d7869cecSEddie James /*
3d7869cecSEddie James  * Copyright 2019 Google LLC
4d7869cecSEddie James  */
5d7869cecSEddie James 
6d7869cecSEddie James #include <common.h>
7d7869cecSEddie James #include <dm.h>
8d7869cecSEddie James #include <log.h>
9d7869cecSEddie James #include <tpm_api.h>
10d7869cecSEddie James #include <tpm-v1.h>
11d7869cecSEddie James #include <tpm-v2.h>
12d7869cecSEddie James #include <tpm_api.h>
13d7869cecSEddie James 
tpm_startup(struct udevice * dev,enum tpm_startup_type mode)14d7869cecSEddie James u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
15d7869cecSEddie James {
16d7869cecSEddie James 	if (tpm_is_v1(dev)) {
17d7869cecSEddie James 		return tpm1_startup(dev, mode);
18d7869cecSEddie James 	} else if (tpm_is_v2(dev)) {
19d7869cecSEddie James 		enum tpm2_startup_types type;
20d7869cecSEddie James 
21d7869cecSEddie James 		switch (mode) {
22d7869cecSEddie James 		case TPM_ST_CLEAR:
23d7869cecSEddie James 			type = TPM2_SU_CLEAR;
24d7869cecSEddie James 			break;
25d7869cecSEddie James 		case TPM_ST_STATE:
26d7869cecSEddie James 			type = TPM2_SU_STATE;
27d7869cecSEddie James 			break;
28d7869cecSEddie James 		default:
29d7869cecSEddie James 		case TPM_ST_DEACTIVATED:
30d7869cecSEddie James 			return -EINVAL;
31d7869cecSEddie James 		}
32d7869cecSEddie James 		return tpm2_startup(dev, type);
33d7869cecSEddie James 	} else {
34d7869cecSEddie James 		return -ENOSYS;
35d7869cecSEddie James 	}
36d7869cecSEddie James }
37d7869cecSEddie James 
tpm_auto_start(struct udevice * dev)38*edd88824SIlias Apalodimas u32 tpm_auto_start(struct udevice *dev)
39*edd88824SIlias Apalodimas {
40*edd88824SIlias Apalodimas 	if (tpm_is_v2(dev))
41*edd88824SIlias Apalodimas 		return tpm2_auto_start(dev);
42*edd88824SIlias Apalodimas 
43*edd88824SIlias Apalodimas 	return -ENOSYS;
44*edd88824SIlias Apalodimas }
45*edd88824SIlias Apalodimas 
tpm_resume(struct udevice * dev)46d7869cecSEddie James u32 tpm_resume(struct udevice *dev)
47d7869cecSEddie James {
48d7869cecSEddie James 	if (tpm_is_v1(dev))
49d7869cecSEddie James 		return tpm1_startup(dev, TPM_ST_STATE);
50d7869cecSEddie James 	else if (tpm_is_v2(dev))
51d7869cecSEddie James 		return tpm2_startup(dev, TPM2_SU_STATE);
52d7869cecSEddie James 	else
53d7869cecSEddie James 		return -ENOSYS;
54d7869cecSEddie James }
55d7869cecSEddie James 
tpm_self_test_full(struct udevice * dev)56d7869cecSEddie James u32 tpm_self_test_full(struct udevice *dev)
57d7869cecSEddie James {
58d7869cecSEddie James 	if (tpm_is_v1(dev))
59d7869cecSEddie James 		return tpm1_self_test_full(dev);
60d7869cecSEddie James 	else if (tpm_is_v2(dev))
61d7869cecSEddie James 		return tpm2_self_test(dev, TPMI_YES);
62d7869cecSEddie James 	else
63d7869cecSEddie James 		return -ENOSYS;
64d7869cecSEddie James }
65d7869cecSEddie James 
tpm_continue_self_test(struct udevice * dev)66d7869cecSEddie James u32 tpm_continue_self_test(struct udevice *dev)
67d7869cecSEddie James {
68d7869cecSEddie James 	if (tpm_is_v1(dev))
69d7869cecSEddie James 		return tpm1_continue_self_test(dev);
70d7869cecSEddie James 	else if (tpm_is_v2(dev))
71d7869cecSEddie James 		return tpm2_self_test(dev, TPMI_NO);
72d7869cecSEddie James 	else
73d7869cecSEddie James 		return -ENOSYS;
74d7869cecSEddie James }
75d7869cecSEddie James 
tpm_clear_and_reenable(struct udevice * dev)76d7869cecSEddie James u32 tpm_clear_and_reenable(struct udevice *dev)
77d7869cecSEddie James {
78d7869cecSEddie James 	u32 ret;
79d7869cecSEddie James 
80d7869cecSEddie James 	log_info("TPM: Clear and re-enable\n");
81d7869cecSEddie James 	ret = tpm_force_clear(dev);
82d7869cecSEddie James 	if (ret != TPM_SUCCESS) {
83d7869cecSEddie James 		log_err("Can't initiate a force clear\n");
84d7869cecSEddie James 		return ret;
85d7869cecSEddie James 	}
86d7869cecSEddie James 
87d7869cecSEddie James 	if (tpm_is_v1(dev)) {
88d7869cecSEddie James 		ret = tpm1_physical_enable(dev);
89d7869cecSEddie James 		if (ret != TPM_SUCCESS) {
90d7869cecSEddie James 			log_err("TPM: Can't set enabled state\n");
91d7869cecSEddie James 			return ret;
92d7869cecSEddie James 		}
93d7869cecSEddie James 
94d7869cecSEddie James 		ret = tpm1_physical_set_deactivated(dev, 0);
95d7869cecSEddie James 		if (ret != TPM_SUCCESS) {
96d7869cecSEddie James 			log_err("TPM: Can't set deactivated state\n");
97d7869cecSEddie James 			return ret;
98d7869cecSEddie James 		}
99d7869cecSEddie James 	}
100d7869cecSEddie James 
101d7869cecSEddie James 	return TPM_SUCCESS;
102d7869cecSEddie James }
103d7869cecSEddie James 
tpm_nv_enable_locking(struct udevice * dev)104d7869cecSEddie James u32 tpm_nv_enable_locking(struct udevice *dev)
105d7869cecSEddie James {
106d7869cecSEddie James 	if (tpm_is_v1(dev))
107d7869cecSEddie James 		return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
108d7869cecSEddie James 	else if (tpm_is_v2(dev))
109d7869cecSEddie James 		return -ENOSYS;
110d7869cecSEddie James 	else
111d7869cecSEddie James 		return -ENOSYS;
112d7869cecSEddie James }
113d7869cecSEddie James 
tpm_nv_read_value(struct udevice * dev,u32 index,void * data,u32 count)114d7869cecSEddie James u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
115d7869cecSEddie James {
116d7869cecSEddie James 	if (tpm_is_v1(dev))
117d7869cecSEddie James 		return tpm1_nv_read_value(dev, index, data, count);
118d7869cecSEddie James 	else if (tpm_is_v2(dev))
119d7869cecSEddie James 		return tpm2_nv_read_value(dev, index, data, count);
120d7869cecSEddie James 	else
121d7869cecSEddie James 		return -ENOSYS;
122d7869cecSEddie James }
123d7869cecSEddie James 
tpm_nv_write_value(struct udevice * dev,u32 index,const void * data,u32 count)124d7869cecSEddie James u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
125d7869cecSEddie James 		       u32 count)
126d7869cecSEddie James {
127d7869cecSEddie James 	if (tpm_is_v1(dev))
128d7869cecSEddie James 		return tpm1_nv_write_value(dev, index, data, count);
129d7869cecSEddie James 	else if (tpm_is_v2(dev))
130d7869cecSEddie James 		return tpm2_nv_write_value(dev, index, data, count);
131d7869cecSEddie James 	else
132d7869cecSEddie James 		return -ENOSYS;
133d7869cecSEddie James }
134d7869cecSEddie James 
tpm_set_global_lock(struct udevice * dev)135d7869cecSEddie James u32 tpm_set_global_lock(struct udevice *dev)
136d7869cecSEddie James {
137d7869cecSEddie James 	return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0);
138d7869cecSEddie James }
139d7869cecSEddie James 
tpm_write_lock(struct udevice * dev,u32 index)140d7869cecSEddie James u32 tpm_write_lock(struct udevice *dev, u32 index)
141d7869cecSEddie James {
142d7869cecSEddie James 	if (tpm_is_v1(dev))
143d7869cecSEddie James 		return -ENOSYS;
144d7869cecSEddie James 	else if (tpm_is_v2(dev))
145d7869cecSEddie James 		return tpm2_write_lock(dev, index);
146d7869cecSEddie James 	else
147d7869cecSEddie James 		return -ENOSYS;
148d7869cecSEddie James }
149d7869cecSEddie James 
tpm_pcr_extend(struct udevice * dev,u32 index,const void * in_digest,uint size,void * out_digest,const char * name)150d7869cecSEddie James u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
151d7869cecSEddie James 		   uint size, void *out_digest, const char *name)
152d7869cecSEddie James {
153d7869cecSEddie James 	if (tpm_is_v1(dev)) {
154d7869cecSEddie James 		return tpm1_extend(dev, index, in_digest, out_digest);
155d7869cecSEddie James 	} else if (tpm_is_v2(dev)) {
156d7869cecSEddie James 		return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest,
157d7869cecSEddie James 				       TPM2_DIGEST_LEN);
158d7869cecSEddie James 		/* @name is ignored as we do not support the TPM log here */
159d7869cecSEddie James 	} else {
160d7869cecSEddie James 		return -ENOSYS;
161d7869cecSEddie James 	}
162d7869cecSEddie James }
163d7869cecSEddie James 
tpm_pcr_read(struct udevice * dev,u32 index,void * data,size_t count)164d7869cecSEddie James u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
165d7869cecSEddie James {
166d7869cecSEddie James 	if (tpm_is_v1(dev))
167d7869cecSEddie James 		return tpm1_pcr_read(dev, index, data, count);
168d7869cecSEddie James 	else if (tpm_is_v2(dev))
169d7869cecSEddie James 		return -ENOSYS;
170d7869cecSEddie James 	else
171d7869cecSEddie James 		return -ENOSYS;
172d7869cecSEddie James }
173d7869cecSEddie James 
tpm_tsc_physical_presence(struct udevice * dev,u16 presence)174d7869cecSEddie James u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
175d7869cecSEddie James {
176d7869cecSEddie James 	if (tpm_is_v1(dev))
177d7869cecSEddie James 		return tpm1_tsc_physical_presence(dev, presence);
178d7869cecSEddie James 
179d7869cecSEddie James 	/*
180d7869cecSEddie James 	 * Nothing to do on TPM2 for this; use platform hierarchy availability
181d7869cecSEddie James 	 * instead.
182d7869cecSEddie James 	 */
183d7869cecSEddie James 	else if (tpm_is_v2(dev))
184d7869cecSEddie James 		return 0;
185d7869cecSEddie James 	else
186d7869cecSEddie James 		return -ENOSYS;
187d7869cecSEddie James }
188d7869cecSEddie James 
tpm_finalise_physical_presence(struct udevice * dev)189d7869cecSEddie James u32 tpm_finalise_physical_presence(struct udevice *dev)
190d7869cecSEddie James {
191d7869cecSEddie James 	if (tpm_is_v1(dev))
192d7869cecSEddie James 		return tpm1_finalise_physical_presence(dev);
193d7869cecSEddie James 
194d7869cecSEddie James 	/* Nothing needs to be done with tpm2 */
195d7869cecSEddie James 	else if (tpm_is_v2(dev))
196d7869cecSEddie James 		return 0;
197d7869cecSEddie James 	else
198d7869cecSEddie James 		return -ENOSYS;
199d7869cecSEddie James }
200d7869cecSEddie James 
tpm_read_pubek(struct udevice * dev,void * data,size_t count)201d7869cecSEddie James u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
202d7869cecSEddie James {
203d7869cecSEddie James 	if (tpm_is_v1(dev))
204d7869cecSEddie James 		return tpm1_read_pubek(dev, data, count);
205d7869cecSEddie James 	else if (tpm_is_v2(dev))
206d7869cecSEddie James 		return -ENOSYS; /* not implemented yet */
207d7869cecSEddie James 	else
208d7869cecSEddie James 		return -ENOSYS;
209d7869cecSEddie James }
210d7869cecSEddie James 
tpm_force_clear(struct udevice * dev)211d7869cecSEddie James u32 tpm_force_clear(struct udevice *dev)
212d7869cecSEddie James {
213d7869cecSEddie James 	if (tpm_is_v1(dev))
214d7869cecSEddie James 		return tpm1_force_clear(dev);
215d7869cecSEddie James 	else if (tpm_is_v2(dev))
216d7869cecSEddie James 		return tpm2_clear(dev, TPM2_RH_PLATFORM, NULL, 0);
217d7869cecSEddie James 	else
218d7869cecSEddie James 		return -ENOSYS;
219d7869cecSEddie James }
220d7869cecSEddie James 
tpm_physical_enable(struct udevice * dev)221d7869cecSEddie James u32 tpm_physical_enable(struct udevice *dev)
222d7869cecSEddie James {
223d7869cecSEddie James 	if (tpm_is_v1(dev))
224d7869cecSEddie James 		return tpm1_physical_enable(dev);
225d7869cecSEddie James 
226d7869cecSEddie James 	/* Nothing needs to be done with tpm2 */
227d7869cecSEddie James 	else if (tpm_is_v2(dev))
228d7869cecSEddie James 		return 0;
229d7869cecSEddie James 	else
230d7869cecSEddie James 		return -ENOSYS;
231d7869cecSEddie James }
232d7869cecSEddie James 
tpm_physical_disable(struct udevice * dev)233d7869cecSEddie James u32 tpm_physical_disable(struct udevice *dev)
234d7869cecSEddie James {
235d7869cecSEddie James 	if (tpm_is_v1(dev))
236d7869cecSEddie James 		return tpm1_physical_disable(dev);
237d7869cecSEddie James 
238d7869cecSEddie James 	/* Nothing needs to be done with tpm2 */
239d7869cecSEddie James 	else if (tpm_is_v2(dev))
240d7869cecSEddie James 		return 0;
241d7869cecSEddie James 	else
242d7869cecSEddie James 		return -ENOSYS;
243d7869cecSEddie James }
244d7869cecSEddie James 
tpm_physical_set_deactivated(struct udevice * dev,u8 state)245d7869cecSEddie James u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
246d7869cecSEddie James {
247d7869cecSEddie James 	if (tpm_is_v1(dev))
248d7869cecSEddie James 		return tpm1_physical_set_deactivated(dev, state);
249d7869cecSEddie James 	/* Nothing needs to be done with tpm2 */
250d7869cecSEddie James 	else if (tpm_is_v2(dev))
251d7869cecSEddie James 		return 0;
252d7869cecSEddie James 	else
253d7869cecSEddie James 		return -ENOSYS;
254d7869cecSEddie James }
255d7869cecSEddie James 
tpm_get_capability(struct udevice * dev,u32 cap_area,u32 sub_cap,void * cap,size_t count)256d7869cecSEddie James u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
257d7869cecSEddie James 		       void *cap, size_t count)
258d7869cecSEddie James {
259d7869cecSEddie James 	if (tpm_is_v1(dev))
260d7869cecSEddie James 		return tpm1_get_capability(dev, cap_area, sub_cap, cap, count);
261d7869cecSEddie James 	else if (tpm_is_v2(dev))
262d7869cecSEddie James 		return tpm2_get_capability(dev, cap_area, sub_cap, cap, count);
263d7869cecSEddie James 	else
264d7869cecSEddie James 		return -ENOSYS;
265d7869cecSEddie James }
266d7869cecSEddie James 
tpm_get_permissions(struct udevice * dev,u32 index,u32 * perm)267d7869cecSEddie James u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
268d7869cecSEddie James {
269d7869cecSEddie James 	if (tpm_is_v1(dev))
270d7869cecSEddie James 		return tpm1_get_permissions(dev, index, perm);
271d7869cecSEddie James 	else if (tpm_is_v2(dev))
272d7869cecSEddie James 		return -ENOSYS; /* not implemented yet */
273d7869cecSEddie James 	else
274d7869cecSEddie James 		return -ENOSYS;
275d7869cecSEddie James }
276d7869cecSEddie James 
tpm_get_random(struct udevice * dev,void * data,u32 count)277d7869cecSEddie James u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
278d7869cecSEddie James {
279d7869cecSEddie James 	if (tpm_is_v1(dev))
280d7869cecSEddie James 		return tpm1_get_random(dev, data, count);
281d7869cecSEddie James 	else if (tpm_is_v2(dev))
282d7869cecSEddie James 		return tpm2_get_random(dev, data, count);
283d7869cecSEddie James 
284d7869cecSEddie James 	return -ENOSYS;
285d7869cecSEddie James }
286