1 //
2 // Copyright (C) 2022 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 //! KeyMint TA core for Cuttlefish.
17
18 extern crate alloc;
19
20 use kmr_common::crypto;
21 use kmr_crypto_boring::{
22 aes::BoringAes, aes_cmac::BoringAesCmac, des::BoringDes, ec::BoringEc, eq::BoringEq,
23 hmac::BoringHmac, rng::BoringRng, rsa::BoringRsa,
24 };
25 use kmr_ta::device::{BootloaderDone, Implementation, TrustedPresenceUnsupported};
26 use kmr_ta::{HardwareInfo, KeyMintTa, RpcInfo, RpcInfoV3};
27 use kmr_wire::keymint::SecurityLevel;
28 use kmr_wire::rpc::MINIMUM_SUPPORTED_KEYS_IN_CSR;
29 use libc::c_int;
30 use log::{error, info, trace};
31 use std::ffi::CString;
32 use std::io::{Read, Write};
33 use std::os::unix::{ffi::OsStrExt, io::FromRawFd};
34
35 pub mod attest;
36 mod clock;
37 pub mod rpc;
38 mod soft;
39 mod tpm;
40
41 #[cfg(test)]
42 mod tests;
43
44 /// Main routine for the KeyMint TA. Only returns if there is a fatal error.
ta_main(fd_in: c_int, fd_out: c_int, security_level: SecurityLevel, trm: *mut libc::c_void)45 pub fn ta_main(fd_in: c_int, fd_out: c_int, security_level: SecurityLevel, trm: *mut libc::c_void) {
46 log::set_logger(&AndroidCppLogger).unwrap();
47 log::set_max_level(log::LevelFilter::Debug); // Filtering happens elsewhere
48 info!(
49 "KeyMint Rust TA running with fd_in={}, fd_out={}, security_level={:?}",
50 fd_in, fd_out, security_level,
51 );
52
53 // Safety: the following calls rely on this code being the sole owner of the file descriptors.
54 let mut infile = unsafe { std::fs::File::from_raw_fd(fd_in) };
55 let mut outfile = unsafe { std::fs::File::from_raw_fd(fd_out) };
56
57 let hw_info = HardwareInfo {
58 version_number: 1,
59 security_level,
60 impl_name: "Rust reference implementation for Cuttlefish",
61 author_name: "Google",
62 unique_id: "Cuttlefish KeyMint TA",
63 };
64
65 let rpc_info_v3 = RpcInfoV3 {
66 author_name: "Google",
67 unique_id: "Cuttlefish KeyMint TA",
68 fused: false,
69 supported_num_of_keys_in_csr: MINIMUM_SUPPORTED_KEYS_IN_CSR,
70 };
71
72 let mut rng = BoringRng::default();
73 let clock = clock::StdClock::default();
74 let rsa = BoringRsa::default();
75 let ec = BoringEc::default();
76 let tpm_hkdf = tpm::KeyDerivation::new(trm);
77 let soft_hkdf = BoringHmac;
78 let hkdf: &dyn kmr_common::crypto::Hkdf =
79 if security_level == SecurityLevel::TrustedEnvironment { &tpm_hkdf } else { &soft_hkdf };
80 let imp = crypto::Implementation {
81 rng: &mut rng,
82 clock: Some(&clock),
83 compare: &BoringEq,
84 aes: &BoringAes,
85 des: &BoringDes,
86 hmac: &BoringHmac,
87 rsa: &rsa,
88 ec: &ec,
89 ckdf: &BoringAesCmac,
90 hkdf,
91 };
92 let sign_info = attest::CertSignInfo::new();
93
94 let tpm_keys = tpm::Keys::new(trm);
95 let soft_keys = soft::Keys;
96 let keys: &dyn kmr_ta::device::RetrieveKeyMaterial =
97 if security_level == SecurityLevel::TrustedEnvironment { &tpm_keys } else { &soft_keys };
98 let tpm_rpc = tpm::RpcArtifacts::new(tpm::TpmHmac::new(trm));
99 let soft_rpc = soft::RpcArtifacts::new(soft::Derive::default());
100 let rpc: &dyn kmr_ta::device::RetrieveRpcArtifacts =
101 if security_level == SecurityLevel::TrustedEnvironment { &tpm_rpc } else { &soft_rpc };
102 let dev = Implementation {
103 keys,
104 sign_info: &sign_info,
105 // HAL populates attestation IDs from properties.
106 attest_ids: None,
107 // No secure storage.
108 sdd_mgr: None,
109 // `BOOTLOADER_ONLY` keys not supported.
110 bootloader: &BootloaderDone,
111 // `STORAGE_KEY` keys not supported.
112 sk_wrapper: None,
113 // `TRUSTED_USER_PRESENCE_REQUIRED` keys not supported
114 tup: &TrustedPresenceUnsupported,
115 // No support for converting previous implementation's keyblobs.
116 legacy_key: None,
117 rpc,
118 };
119 let mut ta = KeyMintTa::new(hw_info, RpcInfo::V3(rpc_info_v3), imp, dev);
120
121 let mut buf = [0; kmr_wire::DEFAULT_MAX_SIZE];
122 loop {
123 // Read a request message from the pipe, as a 4-byte BE length followed by the message.
124 let mut req_len_data = [0u8; 4];
125 if let Err(e) = infile.read_exact(&mut req_len_data) {
126 error!("FATAL: Failed to read request length from connection: {:?}", e);
127 return;
128 }
129 let req_len = u32::from_be_bytes(req_len_data) as usize;
130 if req_len > kmr_wire::DEFAULT_MAX_SIZE {
131 error!("FATAL: Request too long ({})", req_len);
132 return;
133 }
134 let req_data = &mut buf[..req_len];
135 if let Err(e) = infile.read_exact(req_data) {
136 error!(
137 "FATAL: Failed to read request data of length {} from connection: {:?}",
138 req_len, e
139 );
140 return;
141 }
142
143 // Pass to the TA to process.
144 trace!("-> TA: received data: (len={})", req_data.len());
145 let rsp = ta.process(req_data);
146 trace!("<- TA: send data: (len={})", rsp.len());
147
148 // Send the response message down the pipe, as a 4-byte BE length followed by the message.
149 let rsp_len: u32 = match rsp.len().try_into() {
150 Ok(l) => l,
151 Err(_e) => {
152 error!("FATAL: Response too long (len={})", rsp.len());
153 return;
154 }
155 };
156 let rsp_len_data = rsp_len.to_be_bytes();
157 if let Err(e) = outfile.write_all(&rsp_len_data[..]) {
158 error!("FATAL: Failed to write response length to connection: {:?}", e);
159 return;
160 }
161 if let Err(e) = outfile.write_all(&rsp) {
162 error!(
163 "FATAL: Failed to write response data of length {} to connection: {:?}",
164 rsp_len, e
165 );
166 return;
167 }
168 let _ = outfile.flush();
169 }
170 }
171
172 // TODO(schuffelen): Use android_logger when rust works with host glibc, see aosp/1415969
173 struct AndroidCppLogger;
174
175 impl log::Log for AndroidCppLogger {
enabled(&self, _metadata: &log::Metadata) -> bool176 fn enabled(&self, _metadata: &log::Metadata) -> bool {
177 // Filtering is done in the underlying C++ logger, so indicate to the Rust code that all
178 // logs should be included
179 true
180 }
181
log(&self, record: &log::Record)182 fn log(&self, record: &log::Record) {
183 let file = record.file().unwrap_or("(no file)");
184 let file_basename =
185 std::path::Path::new(file).file_name().unwrap_or(std::ffi::OsStr::new("(no file)"));
186 let file = CString::new(file_basename.as_bytes())
187 .unwrap_or_else(|_| CString::new("(invalid file)").unwrap());
188 let line = record.line().unwrap_or(0);
189 let severity = match record.level() {
190 log::Level::Trace => 0,
191 log::Level::Debug => 1,
192 log::Level::Info => 2,
193 log::Level::Warn => 3,
194 log::Level::Error => 4,
195 };
196 let tag = CString::new("secure_env::".to_owned() + record.target())
197 .unwrap_or_else(|_| CString::new("(invalid tag)").unwrap());
198 let msg = CString::new(format!("{}", record.args()))
199 .unwrap_or_else(|_| CString::new("(invalid msg)").unwrap());
200 unsafe {
201 // Safety: All pointer arguments are generated from valid owned CString instances
202 secure_env_tpm::secure_env_log(
203 file.as_ptr(),
204 line,
205 severity,
206 tag.as_ptr(),
207 msg.as_ptr(),
208 );
209 }
210 }
211
flush(&self)212 fn flush(&self) {}
213 }
214