Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/vtpm_proxy.rs
5394 views
1
// Copyright 2022 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
//! vTPM Proxy backend using the vtpmd on ChromeOS to virtualize TPM commands.
6
7
use std::time::Duration;
8
9
use base::error;
10
use protobuf::Message;
11
use remain::sorted;
12
use system_api::client::OrgChromiumVtpm;
13
use system_api::vtpm_interface::SendCommandRequest;
14
use system_api::vtpm_interface::SendCommandResponse;
15
use thiserror::Error;
16
17
use super::virtio::TpmBackend;
18
19
// 5 minutes is the default timeout for tpm commands.
20
const VTPM_DBUS_TIMEOUT: Duration = Duration::from_secs(300);
21
22
// The response of TPM_RC_INSUFFICIENT
23
const TPM_RC_INSUFFICIENT_RESPONSE: &[u8] = &[
24
0x80, 0x01, // TPM_ST_NO_SESSIONS
25
0x00, 0x00, 0x00, 0x0A, // Header Size = 10
26
0x00, 0x00, 0x00, 0x9A, // TPM_RC_INSUFFICIENT
27
];
28
29
// The response of TPM_RC_FAILURE
30
const TPM_RC_FAILURE_RESPONSE: &[u8] = &[
31
0x80, 0x01, // TPM_ST_NO_SESSIONS
32
0x00, 0x00, 0x00, 0x0A, // Header Size = 10
33
0x00, 0x00, 0x01, 0x01, // TPM_RC_FAILURE
34
];
35
36
/// A proxy object that connects to the vtpmd on ChromeOS.
37
pub struct VtpmProxy {
38
dbus_connection: Option<dbus::blocking::Connection>,
39
buf: Vec<u8>,
40
}
41
42
impl VtpmProxy {
43
/// Returns a proxy that can be connected to the vtpmd.
44
pub fn new() -> Self {
45
VtpmProxy {
46
dbus_connection: None,
47
buf: Vec::new(),
48
}
49
}
50
51
fn get_or_create_dbus_connection(
52
&mut self,
53
) -> anyhow::Result<&dbus::blocking::Connection, dbus::Error> {
54
match self.dbus_connection {
55
Some(ref dbus_connection) => Ok(dbus_connection),
56
None => {
57
let dbus_connection = dbus::blocking::Connection::new_system()?;
58
self.dbus_connection = Some(dbus_connection);
59
self.get_or_create_dbus_connection()
60
}
61
}
62
}
63
64
fn try_execute_command(&mut self, command: &[u8]) -> anyhow::Result<(), Error> {
65
let dbus_connection = self
66
.get_or_create_dbus_connection()
67
.map_err(Error::DBusError)?;
68
69
let proxy = dbus_connection.with_proxy(
70
"org.chromium.Vtpm",
71
"/org/chromium/Vtpm",
72
VTPM_DBUS_TIMEOUT,
73
);
74
75
let mut proto = SendCommandRequest::new();
76
proto.set_command(command.to_vec());
77
78
let bytes = proto.write_to_bytes().map_err(Error::ProtobufError)?;
79
80
let resp_bytes = proxy.send_command(bytes).map_err(Error::DBusError)?;
81
82
let response =
83
SendCommandResponse::parse_from_bytes(&resp_bytes).map_err(Error::ProtobufError)?;
84
85
self.buf = response.response().to_vec();
86
87
Ok(())
88
}
89
}
90
91
impl Default for VtpmProxy {
92
fn default() -> Self {
93
Self::new()
94
}
95
}
96
97
impl TpmBackend for VtpmProxy {
98
fn execute_command<'a>(&'a mut self, command: &[u8]) -> &'a [u8] {
99
match self.try_execute_command(command) {
100
Ok(()) => &self.buf,
101
Err(e) => {
102
error!("{:#}", e);
103
match e {
104
Error::ProtobufError(_) => TPM_RC_INSUFFICIENT_RESPONSE,
105
Error::DBusError(_) => TPM_RC_FAILURE_RESPONSE,
106
}
107
}
108
}
109
}
110
}
111
112
#[sorted]
113
#[derive(Error, Debug)]
114
enum Error {
115
#[error("D-Bus failure: {0:#}")]
116
DBusError(dbus::Error),
117
#[error("protocol buffers failure: {0:#}")]
118
ProtobufError(protobuf::Error),
119
}
120
121