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