Implement GetCapabilities and reading flags for tpm2
[vboot.git] / firmware / lib / tpm2_lite / tlcl.c
1 /*
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.
5  *
6  * Some TPM constants and type definitions for standalone compilation for use
7  * in the firmware
8  */
9
10 #include "rollback_index.h"
11 #include "tpm2_marshaling.h"
12 #include "utility.h"
13
14 static struct tpm2_response *tpm_process_command(TPM_CC command,
15                                                  void *command_body)
16 {
17         /* Command/response buffer. */
18         static uint8_t cr_buffer[TPM_BUFFER_SIZE];
19         uint32_t out_size, in_size;
20         struct tpm2_response *response;
21
22         out_size = tpm_marshal_command(command, command_body,
23                                        cr_buffer, sizeof(cr_buffer));
24         if (out_size < 0) {
25                 VBDEBUG(("command %#x, cr size %d\n",
26                          command, out_size));
27                 return NULL;
28         }
29
30         in_size = sizeof(cr_buffer);
31         if (VbExTpmSendReceive(cr_buffer, out_size,
32                                cr_buffer, &in_size) != TPM_SUCCESS) {
33                 VBDEBUG(("tpm transaction failed for %#x\n", command));
34                 return NULL;
35         }
36
37         response = tpm_unmarshal_response(command, cr_buffer, in_size);
38
39         VBDEBUG(("%s: command %#x, return code %#x\n", __func__, command,
40                  response ? response->hdr.tpm_code : -1));
41
42         return response;
43 }
44
45 uint32_t TlclLibInit(void)
46 {
47         return VbExTpmInit();
48 }
49
50 uint32_t TlclLibClose(void)
51 {
52         return VbExTpmClose();
53 }
54
55 void TlclLibAccessAsUser(void)
56 {
57         tpm_set_ph_disabled(1);
58 }
59
60 uint32_t TlclSendReceive(const uint8_t *request, uint8_t *response,
61                          int max_length)
62 {
63         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
64         return TPM_SUCCESS;
65 }
66
67 int TlclPacketSize(const uint8_t *packet)
68 {
69         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
70         return 0;
71 }
72
73 uint32_t TlclStartup(void)
74 {
75         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
76         return TPM_SUCCESS;
77 }
78
79 uint32_t TlclSaveState(void)
80 {
81         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
82         return TPM_SUCCESS;
83 }
84
85 uint32_t TlclResume(void)
86 {
87         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
88         return TPM_SUCCESS;
89 }
90
91 uint32_t TlclSelfTestFull(void)
92 {
93         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
94         return TPM_SUCCESS;
95 }
96
97 uint32_t TlclContinueSelfTest(void)
98 {
99         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
100         return TPM_SUCCESS;
101 }
102
103 int32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size)
104 {
105         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
106         return TPM_SUCCESS;
107 }
108
109 /**
110  * Issue a ForceClear.  The TPM error code is returned.
111  */
112 uint32_t TlclForceClear(void)
113 {
114         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
115         return TPM_SUCCESS;
116 }
117
118 uint32_t TlclSetDeactivated(uint8_t flag)
119 {
120         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
121         return TPM_SUCCESS;
122 }
123
124 uint32_t TlclSetEnable(void)
125 {
126         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
127         return TPM_SUCCESS;
128 }
129
130 uint32_t TlclGetFlags(uint8_t* disable,
131                       uint8_t* deactivated,
132                       uint8_t *nvlocked)
133 {
134         /* For TPM2 the flags are always the same */
135         if (disable)
136                 *disable = 0;
137         if (deactivated)
138                 *deactivated = 0;
139         if (nvlocked)
140                 *nvlocked = 1;
141         return TPM_SUCCESS;
142 }
143
144 int TlclIsOwned(void)
145 {
146         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
147         return 0;
148 }
149
150 uint32_t TlclExtend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest)
151 {
152         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
153         return TPM_SUCCESS;
154 }
155
156 /**
157  * Get the permission bits for the NVRAM space with |index|.
158  */
159 uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions)
160 {
161         *permissions = 0;
162         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
163         return TPM_SUCCESS;
164 }
165
166 static uint32_t tlcl_get_capability(TPM_CAP cap, TPM_PT property,
167                                     struct get_capability_response **presp)
168 {
169         struct tpm2_response *response;
170         struct tpm2_get_capability_cmd getcap;
171
172         getcap.capability = cap;
173         getcap.property = property;
174         getcap.property_count = 1;
175
176         response = tpm_process_command(TPM2_GetCapability, &getcap);
177         if (!response || response->hdr.tpm_code)
178                 return TPM_E_IOERROR;
179         *presp = &response->cap;
180
181         return TPM_SUCCESS;
182 }
183
184 static uint32_t tlcl_get_tpm_property(TPM_PT property, uint32_t *pvalue)
185 {
186         uint32_t rv;
187         struct get_capability_response *resp;
188         TPML_TAGGED_TPM_PROPERTY *tpm_prop;
189
190         rv = tlcl_get_capability(TPM_CAP_TPM_PROPERTIES, property, &resp);
191         if (rv != TPM_SUCCESS)
192                 return rv;
193
194         if (resp->capability_data.capability != TPM_CAP_TPM_PROPERTIES)
195                 return TPM_E_IOERROR;
196
197         tpm_prop = &resp->capability_data.data.tpm_properties;
198
199         if ((tpm_prop->count != 1) ||
200             (tpm_prop->tpm_property[0].property != property))
201                 return TPM_E_IOERROR;
202
203         *pvalue = tpm_prop->tpm_property[0].value;
204         return TPM_SUCCESS;
205 }
206
207 uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags)
208 {
209         return tlcl_get_tpm_property(TPM_PT_PERMANENT,
210                                      (uint32_t *)pflags);
211 }
212
213 uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS *pflags)
214 {
215         return tlcl_get_tpm_property(TPM_PT_STARTUP_CLEAR,
216                                      (uint32_t *)pflags);
217 }
218
219 uint32_t TlclGetOwnership(uint8_t *owned)
220 {
221         *owned = 0;
222         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
223         return TPM_SUCCESS;
224 }
225
226 static uint32_t tlcl_lock_nv_write(uint32_t index)
227 {
228         struct tpm2_response *response;
229         struct tpm2_nv_write_lock_cmd nv_wl;
230
231         nv_wl.nvIndex = HR_NV_INDEX + index;
232         response = tpm_process_command(TPM2_NV_WriteLock, &nv_wl);
233
234         if (!response || response->hdr.tpm_code)
235                 return TPM_E_INTERNAL_INCONSISTENCY;
236
237         return TPM_SUCCESS;
238 }
239
240 static uint32_t tlcl_disable_platform_hierarchy(void)
241 {
242         struct tpm2_response *response;
243         struct tpm2_hierarchy_control_cmd hc;
244
245         hc.enable = TPM_RH_PLATFORM;
246         hc.state = 0;
247
248         response = tpm_process_command(TPM2_Hierarchy_Control, &hc);
249
250         if (!response || response->hdr.tpm_code)
251                 return TPM_E_INTERNAL_INCONSISTENCY;
252
253         return TPM_SUCCESS;
254 }
255
256 /**
257  * Turn off physical presence and locks it off until next reboot.  The TPM
258  * error code is returned.
259  *
260  * The name of the function was kept to maintain the existing TPM API, but
261  * TPM2.0 does not have to use the Physical Presence concept. Instead it just
262  * removes platform authorization - this makes sure that firmware and kernel
263  * rollback counter spaces can not be modified.
264  *
265  * It also explicitly locks the kernel rollback counter space (the FW rollback
266  * counter space was locked before RW firmware started.)
267  */
268 uint32_t TlclLockPhysicalPresence(void)
269 {
270         uint32_t rv;
271
272         rv = tlcl_lock_nv_write(KERNEL_NV_INDEX);
273         if (rv == TPM_SUCCESS)
274                 rv = tlcl_disable_platform_hierarchy();
275
276         return rv;
277 }
278
279 uint32_t TlclRead(uint32_t index, void* data, uint32_t length)
280 {
281         struct tpm2_nv_read_cmd nv_readc;
282         struct tpm2_response *response;
283
284         Memset(&nv_readc, 0, sizeof(nv_readc));
285
286         nv_readc.nvIndex = HR_NV_INDEX + index;
287         nv_readc.size = length;
288
289         response = tpm_process_command(TPM2_NV_Read, &nv_readc);
290
291         /* Need to map tpm error codes into internal values. */
292         if (!response)
293                 return TPM_E_READ_FAILURE;
294
295         switch (response->hdr.tpm_code) {
296         case 0:
297                 break;
298
299         case 0x28b:
300                 return TPM_E_BADINDEX;
301
302         default:
303                 return TPM_E_READ_FAILURE;
304         }
305
306         if (length > response->nvr.buffer.t.size)
307                 return TPM_E_RESPONSE_TOO_LARGE;
308
309         if (length < response->nvr.buffer.t.size)
310                 return TPM_E_READ_EMPTY;
311
312         Memcpy(data, response->nvr.buffer.t.buffer, length);
313
314         return TPM_SUCCESS;
315 }
316
317 uint32_t TlclWrite(uint32_t index, const void *data, uint32_t length)
318 {
319         struct tpm2_nv_write_cmd nv_writec;
320         struct tpm2_response *response;
321
322         Memset(&nv_writec, 0, sizeof(nv_writec));
323
324         nv_writec.nvIndex = HR_NV_INDEX + index;
325         nv_writec.data.t.size = length;
326         nv_writec.data.t.buffer = data;
327
328         response = tpm_process_command(TPM2_NV_Write, &nv_writec);
329
330         /* Need to map tpm error codes into internal values. */
331         if (!response)
332                 return TPM_E_WRITE_FAILURE;
333
334         return TPM_SUCCESS;
335 }
336
337 int32_t TlclPCRRead(uint32_t index, void *data, uint32_t length)
338 {
339         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
340         return TPM_SUCCESS;
341 }
342
343 uint32_t TlclWriteLock(uint32_t index)
344 {
345         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
346         return TPM_SUCCESS;
347 }
348
349 uint32_t TlclReadLock(uint32_t index)
350 {
351         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
352         return TPM_SUCCESS;
353 }
354
355 uint32_t TlclGetRandom(uint8_t *data, uint32_t length, uint32_t *size)
356 {
357         *size = 0;
358         VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
359         return TPM_E_IOERROR;
360 }