blob: dea38abf02252e377389182542fdf7cb49efdc4b (
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
|
/*
* Copyright 2018 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.
*/
#include "config.h"
#include "Global.h"
#include "board.h"
#include "closed_source_set1.h"
#include "console.h"
#include "dcrypto.h"
#include "extension.h"
#include "hooks.h"
#include "nvmem.h"
#include "system.h"
#include "timer.h"
#include "tpm_registers.h"
#include "tpm_vendor_cmds.h"
#define CPRINTS(format, args...) cprints(CC_EXTENSION, format, ## args)
static void disable_tpm(void)
{
tpm_stop();
DCRYPTO_ladder_revoke();
nvmem_clear_cache();
if (board_uses_closed_source_set1())
close_source_set1_disable_tpm();
}
DECLARE_DEFERRED(disable_tpm);
/*
* On TPM reset event, tpm_reset_now() in tpm_registers.c clears TPM2 BSS memory
* area. By placing s_tpm_mode in TPM2 BSS area, TPM mode value shall be
* "TPM_MODE_ENABLED_TENTATIVE" on every TPM reset events.
*/
static enum tpm_modes s_tpm_mode __attribute__((section(".bss.Tpm2_common")));
static enum vendor_cmd_rc process_tpm_mode(struct vendor_cmd_params *p)
{
uint8_t mode_val;
uint8_t *buffer;
p->out_size = 0;
if (p->in_size > sizeof(uint8_t))
return VENDOR_RC_NOT_ALLOWED;
buffer = (uint8_t *)p->buffer;
if (p->in_size == sizeof(uint8_t)) {
if (!board_tpm_mode_change_allowed() ||
(s_tpm_mode != TPM_MODE_ENABLED_TENTATIVE))
return VENDOR_RC_NOT_ALLOWED;
mode_val = buffer[0];
switch (mode_val) {
case TPM_MODE_ENABLED:
/*
* If Key ladder is disabled, then fail this request.
*/
if (!DCRYPTO_ladder_is_enabled())
return VENDOR_RC_INTERNAL_ERROR;
break;
case TPM_MODE_DISABLED:
/*
* If it is to be disabled, call disable_tpm() deferred
* so that this vendor command can be responded to
* before TPM stops.
*/
if (nvmem_enable_commits() != EC_SUCCESS)
return VENDOR_RC_NVMEM_LOCKED;
hook_call_deferred(&disable_tpm_data, 10 * MSEC);
break;
default:
return VENDOR_RC_NO_SUCH_SUBCOMMAND;
}
s_tpm_mode = mode_val;
} else {
if (s_tpm_mode < TPM_MODE_DISABLED &&
!DCRYPTO_ladder_is_enabled())
return VENDOR_RC_INTERNAL_ERROR;
}
p->out_size = sizeof(uint8_t);
buffer[0] = (uint8_t) s_tpm_mode;
return VENDOR_RC_SUCCESS;
}
DECLARE_VENDOR_COMMAND_P(VENDOR_CC_TPM_MODE, process_tpm_mode);
enum tpm_modes get_tpm_mode(void)
{
return s_tpm_mode;
}
|