blob: 0c6fd0c56e421024b5c2e798a7a7f6ed618cda70 [file] [log] [blame]
Gaurav Shahce0cc302010-03-24 13:48:55 -07001/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Functions for querying, manipulating and locking rollback indices
6 * stored in the TPM NVRAM.
7 */
8
9#include "rollback_index.h"
10
11#include <stdint.h>
12#include <tss/tcs.h>
13
Gaurav Shahf3dd1a62010-04-05 15:50:00 -070014#include "utility.h"
Gaurav Shahce0cc302010-03-24 13:48:55 -070015#include "tlcl.h"
16
17uint16_t g_firmware_key_version = 0;
18uint16_t g_firmware_version = 0;
19uint16_t g_kernel_key_version = 0;
20uint16_t g_kernel_version = 0;
21
22static void InitializeSpaces(void) {
23 uint16_t zero = 0;
24 uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
25
Gaurav Shahf3dd1a62010-04-05 15:50:00 -070026 debug("Initializing spaces\n");
Gaurav Shahce0cc302010-03-24 13:48:55 -070027 TlclSetNvLocked(); /* useful only the first time */
28
29 TlclDefineSpace(FIRMWARE_KEY_VERSION_NV_INDEX, perm, sizeof(uint16_t));
30 TlclWrite(FIRMWARE_KEY_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));
31
32 TlclDefineSpace(FIRMWARE_VERSION_NV_INDEX, perm, sizeof(uint16_t));
33 TlclWrite(FIRMWARE_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));
34
35 TlclDefineSpace(KERNEL_KEY_VERSION_NV_INDEX, perm, sizeof(uint16_t));
36 TlclWrite(KERNEL_KEY_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));
37
38 TlclDefineSpace(KERNEL_VERSION_NV_INDEX, perm, sizeof(uint16_t));
39 TlclWrite(KERNEL_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));
40}
41
42static void EnterRecovery(void) {
43 /* Temporary recovery stub. Currently just initalizes spaces. */
44 InitializeSpaces();
45}
46
47static int GetTPMRollbackIndices(void) {
48 /* We just perform the reads, making sure they succeed. A failure means that
49 * the rollback index locations are some how messed up and we must jump to
50 * recovery */
51 if (TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
52 (uint8_t*) &g_firmware_key_version,
53 sizeof(g_firmware_key_version)) ||
54 TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
55 (uint8_t*) &g_firmware_key_version,
56 sizeof(g_firmware_key_version)) ||
57 TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
58 (uint8_t*) &g_firmware_key_version,
59 sizeof(g_firmware_key_version)) ||
60 TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
61 (uint8_t*) &g_firmware_key_version,
62 sizeof(g_firmware_key_version)))
63 return 0;
64 return 1;
65}
66
67
68void SetupTPM(void) {
69 TlclLibinit();
70 TlclStartup();
71 /* TODO(gauravsh): The call to self test should probably be deferred.
72 * As per semenzato@chromium.org -
73 * TlclStartup should be called before the firmware initializes the memory
74 * controller, so the selftest can run in parallel with that. Here we should
75 * just call TlclSelftestFull to make sure the self test has
76 * completed---unless we want to rely on the NVRAM operations being available
77 * before the selftest completes. */
78 TlclSelftestfull();
79 TlclAssertPhysicalPresence();
80 if (!GetTPMRollbackIndices()) {
Gaurav Shahf3dd1a62010-04-05 15:50:00 -070081 debug("Ho Ho Ho! We must jump to recovery.");
Gaurav Shahce0cc302010-03-24 13:48:55 -070082 EnterRecovery();
83 }
84}
85
86
87uint16_t GetStoredVersion(int type) {
88 switch (type) {
89 case FIRMWARE_KEY_VERSION:
90 return g_firmware_key_version;
91 break;
92 case FIRMWARE_VERSION:
93 return g_firmware_version;
94 break;
95 case KERNEL_KEY_VERSION:
96 return g_kernel_key_version;
97 break;
98 case KERNEL_VERSION:
99 return g_kernel_version;
100 break;
101 }
102 return 0;
103}
104
105int WriteStoredVersion(int type, uint16_t version) {
106 switch (type) {
107 case FIRMWARE_KEY_VERSION:
108 return (TPM_SUCCESS == TlclWrite(FIRMWARE_KEY_VERSION_NV_INDEX,
109 (uint8_t*) &version,
110 sizeof(uint16_t)));
111 break;
112 case FIRMWARE_VERSION:
113 return (TPM_SUCCESS == TlclWrite(FIRMWARE_VERSION_NV_INDEX,
114 (uint8_t*) &version,
115 sizeof(uint16_t)));
116 break;
117 case KERNEL_KEY_VERSION:
118 return (TPM_SUCCESS == TlclWrite(KERNEL_KEY_VERSION_NV_INDEX,
119 (uint8_t*) &version,
120 sizeof(uint16_t)));
121 break;
122 case KERNEL_VERSION:
123 return (TPM_SUCCESS == TlclWrite(KERNEL_VERSION_NV_INDEX,
124 (uint8_t*) &version,
125 sizeof(uint16_t)));
126 break;
127 }
128 return 0;
129}
130
131void LockStoredVersion(int type) {
132 /* TODO(gauravsh): Add error checking here to make sure TlclWriteLock
133 * did not fail. We must jump to recovery in that case.
134 */
135 switch (type) {
136 case FIRMWARE_KEY_VERSION:
137 TlclWriteLock(FIRMWARE_KEY_VERSION_NV_INDEX);
138 break;
139 case FIRMWARE_VERSION:
140 TlclWriteLock(FIRMWARE_VERSION_NV_INDEX);
141 break;
142 case KERNEL_KEY_VERSION:
143 TlclWriteLock(KERNEL_KEY_VERSION_NV_INDEX);
144 break;
145 case KERNEL_VERSION:
146 TlclWriteLock(KERNEL_VERSION_NV_INDEX);
147 break;
148 }
149}