blob: 0b65bf490f6c574709b7b525773027d73fff407e [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
14#include "tlcl.h"
15
16uint16_t g_firmware_key_version = 0;
17uint16_t g_firmware_version = 0;
18uint16_t g_kernel_key_version = 0;
19uint16_t g_kernel_version = 0;
20
21static void InitializeSpaces(void) {
22 uint16_t zero = 0;
23 uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
24
25 printf("Initializing spaces\n");
26 TlclSetNvLocked(); /* useful only the first time */
27
28 TlclDefineSpace(FIRMWARE_KEY_VERSION_NV_INDEX, perm, sizeof(uint16_t));
29 TlclWrite(FIRMWARE_KEY_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));
30
31 TlclDefineSpace(FIRMWARE_VERSION_NV_INDEX, perm, sizeof(uint16_t));
32 TlclWrite(FIRMWARE_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));
33
34 TlclDefineSpace(KERNEL_KEY_VERSION_NV_INDEX, perm, sizeof(uint16_t));
35 TlclWrite(KERNEL_KEY_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));
36
37 TlclDefineSpace(KERNEL_VERSION_NV_INDEX, perm, sizeof(uint16_t));
38 TlclWrite(KERNEL_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));
39}
40
41static void EnterRecovery(void) {
42 /* Temporary recovery stub. Currently just initalizes spaces. */
43 InitializeSpaces();
44}
45
46static int GetTPMRollbackIndices(void) {
47 /* We just perform the reads, making sure they succeed. A failure means that
48 * the rollback index locations are some how messed up and we must jump to
49 * recovery */
50 if (TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
51 (uint8_t*) &g_firmware_key_version,
52 sizeof(g_firmware_key_version)) ||
53 TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
54 (uint8_t*) &g_firmware_key_version,
55 sizeof(g_firmware_key_version)) ||
56 TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
57 (uint8_t*) &g_firmware_key_version,
58 sizeof(g_firmware_key_version)) ||
59 TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
60 (uint8_t*) &g_firmware_key_version,
61 sizeof(g_firmware_key_version)))
62 return 0;
63 return 1;
64}
65
66
67void SetupTPM(void) {
68 TlclLibinit();
69 TlclStartup();
70 /* TODO(gauravsh): The call to self test should probably be deferred.
71 * As per semenzato@chromium.org -
72 * TlclStartup should be called before the firmware initializes the memory
73 * controller, so the selftest can run in parallel with that. Here we should
74 * just call TlclSelftestFull to make sure the self test has
75 * completed---unless we want to rely on the NVRAM operations being available
76 * before the selftest completes. */
77 TlclSelftestfull();
78 TlclAssertPhysicalPresence();
79 if (!GetTPMRollbackIndices()) {
80 fprintf(stderr, "Ho Ho Ho! We must jump to recovery.");
81 EnterRecovery();
82 }
83}
84
85
86uint16_t GetStoredVersion(int type) {
87 switch (type) {
88 case FIRMWARE_KEY_VERSION:
89 return g_firmware_key_version;
90 break;
91 case FIRMWARE_VERSION:
92 return g_firmware_version;
93 break;
94 case KERNEL_KEY_VERSION:
95 return g_kernel_key_version;
96 break;
97 case KERNEL_VERSION:
98 return g_kernel_version;
99 break;
100 }
101 return 0;
102}
103
104int WriteStoredVersion(int type, uint16_t version) {
105 switch (type) {
106 case FIRMWARE_KEY_VERSION:
107 return (TPM_SUCCESS == TlclWrite(FIRMWARE_KEY_VERSION_NV_INDEX,
108 (uint8_t*) &version,
109 sizeof(uint16_t)));
110 break;
111 case FIRMWARE_VERSION:
112 return (TPM_SUCCESS == TlclWrite(FIRMWARE_VERSION_NV_INDEX,
113 (uint8_t*) &version,
114 sizeof(uint16_t)));
115 break;
116 case KERNEL_KEY_VERSION:
117 return (TPM_SUCCESS == TlclWrite(KERNEL_KEY_VERSION_NV_INDEX,
118 (uint8_t*) &version,
119 sizeof(uint16_t)));
120 break;
121 case KERNEL_VERSION:
122 return (TPM_SUCCESS == TlclWrite(KERNEL_VERSION_NV_INDEX,
123 (uint8_t*) &version,
124 sizeof(uint16_t)));
125 break;
126 }
127 return 0;
128}
129
130void LockStoredVersion(int type) {
131 /* TODO(gauravsh): Add error checking here to make sure TlclWriteLock
132 * did not fail. We must jump to recovery in that case.
133 */
134 switch (type) {
135 case FIRMWARE_KEY_VERSION:
136 TlclWriteLock(FIRMWARE_KEY_VERSION_NV_INDEX);
137 break;
138 case FIRMWARE_VERSION:
139 TlclWriteLock(FIRMWARE_VERSION_NV_INDEX);
140 break;
141 case KERNEL_KEY_VERSION:
142 TlclWriteLock(KERNEL_KEY_VERSION_NV_INDEX);
143 break;
144 case KERNEL_VERSION:
145 TlclWriteLock(KERNEL_VERSION_NV_INDEX);
146 break;
147 }
148}