summaryrefslogtreecommitdiff
path: root/common/rollback_index.c
blob: c107f8e70ea8481e430aaa9f6c50300b7943d8bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Functions for querying, manipulating and locking rollback indices
 * stored in the TPM NVRAM.
 */

#include "rollback_index.h"

#include <stdint.h>
#include <stdio.h>
#include <tss/tcs.h>

#include "tlcl.h"

uint16_t g_firmware_key_version = 0;
uint16_t g_firmware_version = 0;
uint16_t g_kernel_key_version = 0;
uint16_t g_kernel_version = 0;

static void InitializeSpaces(void) {
  uint16_t zero = 0;
  uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;

  fprintf(stderr, "Initializing spaces\n");
  TlclSetNvLocked();  /* useful only the first time */

  TlclDefineSpace(FIRMWARE_KEY_VERSION_NV_INDEX, perm, sizeof(uint16_t));
  TlclWrite(FIRMWARE_KEY_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));

  TlclDefineSpace(FIRMWARE_VERSION_NV_INDEX, perm, sizeof(uint16_t));
  TlclWrite(FIRMWARE_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));

  TlclDefineSpace(KERNEL_KEY_VERSION_NV_INDEX, perm, sizeof(uint16_t));
  TlclWrite(KERNEL_KEY_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));

  TlclDefineSpace(KERNEL_VERSION_NV_INDEX, perm, sizeof(uint16_t));
  TlclWrite(KERNEL_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t));
}

static void EnterRecovery(void) {
  /* Temporary recovery stub. Currently just initalizes spaces. */
  InitializeSpaces();
}

static int GetTPMRollbackIndices(void) {
  /* We just perform the reads, making sure they succeed. A failure means that
   * the rollback index locations are some how messed up and we must jump to
   * recovery */
  if (TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
                              (uint8_t*) &g_firmware_key_version,
                              sizeof(g_firmware_key_version)) ||
      TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
                              (uint8_t*) &g_firmware_key_version,
                              sizeof(g_firmware_key_version)) ||
      TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
                               (uint8_t*) &g_firmware_key_version,
                               sizeof(g_firmware_key_version))  ||
      TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX,
                              (uint8_t*) &g_firmware_key_version,
                              sizeof(g_firmware_key_version)))
    return 0;
  return 1;
}


void SetupTPM(void) {
  TlclLibinit();
  TlclStartup();
  /* TODO(gauravsh): The call to self test  should probably be deferred.
   * As per semenzato@chromium.org -
   * TlclStartup should be called before the firmware initializes the memory
   * controller, so the selftest can run in parallel with that. Here we should
   * just call TlclSelftestFull to make sure the self test has
   * completed---unless we want to rely on the NVRAM operations being available
   * before the selftest completes. */
  TlclSelftestfull();
  TlclAssertPhysicalPresence();
  if (!GetTPMRollbackIndices()) {
    fprintf(stderr, "Ho Ho Ho! We must jump to recovery.");
    EnterRecovery();
  }
}


uint16_t GetStoredVersion(int type) {
  switch (type) {
    case FIRMWARE_KEY_VERSION:
      return g_firmware_key_version;
      break;
    case FIRMWARE_VERSION:
      return g_firmware_version;
      break;
    case KERNEL_KEY_VERSION:
      return g_kernel_key_version;
      break;
    case KERNEL_VERSION:
      return g_kernel_version;
      break;
  }
  return 0;
}

int WriteStoredVersion(int type, uint16_t version) {
  switch (type) {
    case FIRMWARE_KEY_VERSION:
      return (TPM_SUCCESS == TlclWrite(FIRMWARE_KEY_VERSION_NV_INDEX,
                                       (uint8_t*) &version,
                                       sizeof(uint16_t)));
      break;
    case FIRMWARE_VERSION:
      return (TPM_SUCCESS == TlclWrite(FIRMWARE_VERSION_NV_INDEX,
                                       (uint8_t*) &version,
                                       sizeof(uint16_t)));
      break;
    case KERNEL_KEY_VERSION:
      return (TPM_SUCCESS == TlclWrite(KERNEL_KEY_VERSION_NV_INDEX,
                                       (uint8_t*) &version,
                                       sizeof(uint16_t)));
      break;
    case KERNEL_VERSION:
      return (TPM_SUCCESS == TlclWrite(KERNEL_VERSION_NV_INDEX,
                                       (uint8_t*) &version,
                                       sizeof(uint16_t)));
      break;
  }
  return 0;
}

void LockStoredVersion(int type) {
  /* TODO(gauravsh): Add error checking here to make sure TlclWriteLock
   * did not fail. We must jump to recovery in that case.
   */
  switch (type) {
    case FIRMWARE_KEY_VERSION:
      TlclWriteLock(FIRMWARE_KEY_VERSION_NV_INDEX);
      break;
    case FIRMWARE_VERSION:
      TlclWriteLock(FIRMWARE_VERSION_NV_INDEX);
      break;
    case KERNEL_KEY_VERSION:
      TlclWriteLock(KERNEL_KEY_VERSION_NV_INDEX);
      break;
    case KERNEL_VERSION:
      TlclWriteLock(KERNEL_VERSION_NV_INDEX);
      break;
  }
}